diff mbox series

[edk2,v1,1/1] EmbeddedPkg/Drivers: add DwUsbDxe

Message ID 1534851313-21358-1-git-send-email-haojian.zhuang@linaro.org
State New
Headers show
Series [edk2,v1,1/1] EmbeddedPkg/Drivers: add DwUsbDxe | expand

Commit Message

Haojian Zhuang Aug. 21, 2018, 11:35 a.m. UTC
Add Designware USB 2.0 device driver that is used on HiKey platform.

Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

---
 EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec |  45 +
 EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.inf |  52 ++
 EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.h   | 655 ++++++++++++++
 EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.c   | 912 ++++++++++++++++++++
 4 files changed, 1664 insertions(+)

-- 
2.7.4

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

Comments

Leif Lindholm Oct. 5, 2018, 3:46 p.m. UTC | #1
On Tue, Aug 21, 2018 at 07:35:13PM +0800, Haojian Zhuang wrote:
> Add Designware USB 2.0 device driver that is used on HiKey platform.

> 

> Cc: Leif Lindholm <leif.lindholm@linaro.org>

> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> Contributed-under: TianoCore Contribution Agreement 1.1

> Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

> ---

>  EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec |  45 +

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

>  EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.h   | 655 ++++++++++++++

>  EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.c   | 912 ++++++++++++++++++++

>  4 files changed, 1664 insertions(+)


Could it be renamed DwUsb2? This seems to match how Synopsys
themselves refer to it, and what the Linux driver is called.

Other than that, same comments as for DwUsb3Dxe - please move it to
edk2-platforms and convert it to UEFI driver model with
NonDiscoverableDeviceRegistrationLib.

Hmm, it also looks to me like there are plenty of things here
hardcoded for the use as a device for fastboot. I don't object to
that being the only support submitted, you made it clear when you
posted it. But the code is completely geared towards this, and I feel
if someone comes along and want to add the functionality to run it in
host mode.

I expect I will find the same when I look at the reworked version of DwUsb3Dxe.

Is there anything you can do to break out the generic device
configuration bits from the bits that assume there are two endpoints
and they are being used for fastboot?

> 

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

> new file mode 100644

> index 000000000000..7eb65e498c04

> --- /dev/null

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

> @@ -0,0 +1,45 @@

> +#/** @file

> +# Framework Module Development Environment Industry Standards

> +#

> +# This Package provides headers and libraries that conform to EFI/PI Industry standards.

> +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>

> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR>

> +# Copyright (c) 2018, Linaro. All rights reserved.<BR>


Same comments as for DwUsb3 - please merge these two into a common one
for both drivers (if still needed).

> +#

> +#    This program and the accompanying materials are licensed and made available under

> +#    the terms and conditions of the BSD License which accompanies this distribution.

> +#    The full text of the license may be found at

> +#    http://opensource.org/licenses/bsd-license.php

> +#

> +#    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +#    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +#

> +#**/

> +

> +[Defines]

> +  DEC_SPECIFICATION              = 0x00010019

> +  PACKAGE_NAME                   = DwUsbDxePkg

> +  PACKAGE_GUID                   = 114a3be9-10f7-4bf1-81ca-09ac52d4c3d5

> +  PACKAGE_VERSION                = 0.1

> +

> +

> +################################################################################

> +#

> +# Include Section - list of Include Paths that are provided by this package.

> +#                   Comments are used for Keywords and Module Types.

> +#

> +# Supported Module Types:

> +#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION

> +#

> +################################################################################

> +

> +[Guids.common]

> +  gDwUsbDxeTokenSpaceGuid       = { 0x131c4d02, 0x9449, 0x4ee9, { 0xba, 0x3d, 0x69, 0x50, 0x21, 0x89, 0x26, 0x0b }}

> +

> +[Protocols.common]

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

> +

> +[PcdsFixedAtBuild.common]

> +  # DwUsb Driver PCDs

> +  gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0x0|UINT32|0x00000001

> +  gDwUsbDxeTokenSpaceGuid.PcdSysCtrlBaseAddress|0x0|UINT32|0x00000002


I don't see PcdSysCtrlBaseAddress used anywhere in this patch? It also
doesn't sound like something that should be an aspect of the USB
controller driver.

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

> new file mode 100644

> index 000000000000..56d518c27c32

> --- /dev/null

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

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

> +#/** @file

> +#

> +#  Copyright (c) 2018, Linaro. All rights reserved.

> +#

> +#  This program and the accompanying materials are licensed and made available

> +#  under the terms and conditions of the BSD License which accompanies this

> +#  distribution. The full text of the license may be found at

> +#  http://opensource.org/licenses/bsd-license.php

> +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +#

> +#

> +#**/

> +

> +[Defines]

> +  INF_VERSION                    = 0x00010019

> +  BASE_NAME                      = DwUsbDxe

> +  FILE_GUID                      = 72d78ea6-4dee-11e3-8100-f3842a48d0a0

> +  MODULE_TYPE                    = UEFI_DRIVER

> +  VERSION_STRING                 = 1.0

> +  ENTRY_POINT                    = DwUsbEntryPoint

> +

> +[Sources.common]

> +  DwUsbDxe.c

> +

> +[LibraryClasses]

> +  ArmLib


This is not an ARM-specific device, so it should not need ArmLib to build.

> +  CacheMaintenanceLib

> +  DebugLib

> +  DmaLib

> +  IoLib

> +  MemoryAllocationLib

> +  TimerLib

> +  UefiBootServicesTableLib

> +  UefiDriverEntryPoint

> +

> +[Protocols]

> +  gEfiDriverBindingProtocolGuid

> +  gUsbDeviceProtocolGuid

> +

> +[Packages]

> +  ArmPkg/ArmPkg.dec


Hmm?

> +  EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec

> +  EmbeddedPkg/EmbeddedPkg.dec

> +  MdeModulePkg/MdeModulePkg.dec

> +  MdePkg/MdePkg.dec

> +

> +[Pcd]

> +  gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress

> +

> +[Depex]

> +  TRUE

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

> new file mode 100644

> index 000000000000..1595e09a92a4

> --- /dev/null

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

> @@ -0,0 +1,655 @@

> +/** @file

> +

> +  Copyright (c) 2018, Linaro. All rights reserved.

> +

> +  This program and the accompanying materials are licensed and made available

> +  under the terms and conditions of the BSD License which accompanies this

> +  distribution.  The full text of the license may be found at

> +  http://opensource.org/licenses/bsd-license.php

> +

> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +

> +**/

> +

> +#ifndef __DW_USB_DXE_H__

> +#define __DW_USB_DXE_H__


Preferably expand all DW_ to DESIGNWARE_.

> +

> +#define DW_USB_BASE                     FixedPcdGet32 (PcdDwUsbDxeBaseAddress)

> +

> +#define READ_REG32(Offset)              MmioRead32 (DW_USB_BASE + Offset)

> +#define READ_REG16(Offset)              (UINT16)READ_REG32 (Offset)

> +#define WRITE_REG32(Offset, Val)        MmioWrite32 (DW_USB_BASE + Offset, Val)

> +#define WRITE_REG16(Offset, Val)        MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val)

> +#define WRITE_REG8(Offset, Val)         MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val)

> +

> +//

> +// Max packet size in bytes (For Full Speed USB 64 is the only valid value)

> +//

> +#define MAX_PACKET_SIZE_CONTROL         64

> +

> +#define MAX_PACKET_SIZE_BULK            512

> +

> +//

> +// 8 Endpoints, in and out. Don't count the Endpoint 0 setup buffer

> +//

> +#define DW_NUM_ENDPOINTS                16

> +

> +//

> +// Endpoint Indexes

> +//

> +#define DW_EP0SETUP                     0x20

> +#define DW_EP0RX                        0x00

> +#define DW_EP0TX                        0x01

> +#define DW_EP1RX                        0x02

> +#define DW_EP1TX                        0x03

> +

> +//

> +// DcInterrupt bits

> +//

> +#define DW_DC_INTERRUPT_EP1TX           BIT13

> +#define DW_DC_INTERRUPT_EP1RX           BIT12

> +#define DW_DC_INTERRUPT_EP0TX           BIT11

> +#define DW_DC_INTERRUPT_EP0RX           BIT10

> +#define DW_DC_INTERRUPT_EP0SETUP        BIT8

> +#define DW_DC_INTERRUPT_VBUS            BIT7

> +#define DW_DC_INTERRUPT_DMA             BIT6

> +#define DW_DC_INTERRUPT_HS_STAT         BIT5

> +#define DW_DC_INTERRUPT_RESUME          BIT4

> +#define DW_DC_INTERRUPT_SUSP            BIT3

> +#define DW_DC_INTERRUPT_PSOF            BIT2

> +#define DW_DC_INTERRUPT_SOF             BIT1

> +#define DW_DC_INTERRUPT_BRESET          BIT0

> +//

> +// All valid peripheral controller int  rrupts

> +//

> +#define DW_DC_INTERRUPT_MASK            0x003FFFDFF

> +

> +#define DW_ADDRESS                      0x200

> +#define DW_ADDRESS_DEVEN                BIT7

> +

> +#define DW_MODE                         0x20C

> +#define DW_MODE_DATA_BUS_WIDTH          BIT8

> +#define DW_MODE_CLKAON                  BIT7

> +#define DW_MODE_SFRESET                 BIT4

> +#define DW_MODE_WKUPCS                  BIT2

> +

> +#define DW_ENDPOINT_MAX_PACKET_SIZE     0x204

> +

> +#define DW_ENDPOINT_TYPE                0x208

> +#define DW_ENDPOINT_TYPE_NOEMPKT        BIT4

> +#define DW_ENDPOINT_TYPE_ENABLE         BIT3

> +

> +#define DW_INTERRUPT_CONFIG             0x210

> +//

> +// Interrupt config value to only interrupt on ACK of IN and OUT tokens

> +//

> +#define DW_INTERRUPT_CONFIG_ACK_ONLY    (BIT2 | BIT5 | BIT6)

> +

> +#define DW_DC_INTERRUPT                 0x218

> +#define DW_DC_INTERRUPT_ENABLE          0x214

> +

> +#define DW_CTRL_FUNCTION                0x228

> +#define DW_CTRL_FUNCTION_VENDP          BIT3

> +#define DW_CTRL_FUNCTION_DSEN           BIT2

> +#define DW_CTRL_FUNCTION_STATUS         BIT1

> +

> +#define DW_DEVICE_UNLOCK                0x27C

> +#define DW_DEVICE_UNLOCK_MAGIC          0xAA37

> +

> +#define DW_SW_RESET_REG                 0x30C

> +#define DW_SW_RESET_ALL                 BIT0

> +

> +#define DW_DEVICE_ID                    0x370

> +

> +#define DW_OTG_CTRL_SET                 0x374

> +#define DW_OTG_CTRL_CLR                 (OTG_CTRL_SET + 2)

> +#define DW_OTG_CTRL_OTG_DISABLE         BIT10

> +#define DW_OTG_CTRL_VBUS_CHRG           BIT6

> +#define DW_OTG_CTRL_VBUS_DISCHRG        BIT5

> +#define DW_OTG_CTRL_DM_PULLDOWN         BIT2

> +#define DW_OTG_CTRL_DP_PULLDOWN         BIT1

> +#define DW_OTG_CTRL_DP_PULLUP           BIT0

> +

> +#define DW_OTG_STATUS                   0x378

> +#define DW_OTG_STATUS_B_SESS_END        BIT7

> +#define DW_OTG_STATUS_A_B_SESS_VLD      BIT1

> +

> +#define DW_OTG_INTERRUPT_LATCH_SET      0x37C

> +#define DW_OTG_INTERRUPT_LATCH_CLR      0x37E

> +#define DW_OTG_INTERRUPT_ENABLE_RISE    0x384

> +

> +#define DW_DMA_ENDPOINT_INDEX           0x258

> +

> +#define DW_ENDPOINT_INDEX               0x22c

> +#define DW_DATA_PORT                    0x220

> +#define DW_BUFFER_LENGTH                0x21c

> +

> +//

> +// Device ID Values

> +//

> +#define PHILLIPS_VENDOR_ID_VAL          0x04cc

> +#define DW_PRODUCT_ID_VAL               0x1761

> +#define DW_DEVICE_ID_VAL                ((ISP1761_PRODUCT_ID_VAL << 16) | \

> +                                         PHILLIPS_VENDOR_ID_VAL)

> +

> +#define DWC_OTG_BASE                    DW_USB_BASE

> +

> +#define USB_NUM_ENDPOINTS               2

> +#define MAX_EPS_CHANNELS                16

> +

> +#define BULK_OUT_EP                     1

> +#define BULK_IN_EP                      1

> +

> +#define RX_REQ_LEN                      512

> +#define MAX_PACKET_LEN                  512

> +

> +#define DATA_FIFO_CONFIG                0x0F801000

> +/* RX FIFO: 2048 bytes */

> +#define RX_SIZE                         0x00000200

> +/* Non-periodic TX FIFO: 128 bytes. start address: 0x200 * 4. */

> +#define ENDPOINT_TX_SIZE                0x01000200

> +

> +/* EP1  TX FIFO: 1024 bytes. start address: 0x220 * 4. */

> +/* EP2  TX FIFO: 1024 bytes. start address: 0x320 * 4. */

> +/* EP3  TX FIFO: 1024 bytes. start address: 0x420 * 4. */

> +/* EP4  TX FIFO: 1024 bytes. start address: 0x520 * 4. */

> +/* EP5  TX FIFO: 128 bytes. start address: 0x620 * 4. */

> +/* EP6  TX FIFO: 128 bytes. start address: 0x640 * 4. */

> +/* EP7  TX FIFO: 128 bytes. start address: 0x660 * 4. */

> +/* EP8  TX FIFO: 128 bytes. start address: 0x680 * 4. */

> +/* EP9  TX FIFO: 128 bytes. start address: 0x6A0 * 4. */

> +/* EP10 TX FIFO: 128 bytes. start address: 0x6C0 * 4. */

> +/* EP11 TX FIFO: 128  bytes. start address: 0x6E0 * 4. */

> +/* EP12 TX FIFO: 128  bytes. start address: 0x700 * 4. */

> +/* EP13 TX FIFO: 128  bytes. start address: 0x720 * 4. */

> +/* EP14 TX FIFO: 128  bytes. start address: 0x740 * 4. */

> +/* EP15 TX FIFO: 128  bytes. start address: 0x760 * 4. */

> +

> +#define DATA_IN_ENDPOINT_TX_FIFO1       0x01000220

> +#define DATA_IN_ENDPOINT_TX_FIFO2       0x01000320

> +#define DATA_IN_ENDPOINT_TX_FIFO3       0x01000420

> +#define DATA_IN_ENDPOINT_TX_FIFO4       0x01000520

> +#define DATA_IN_ENDPOINT_TX_FIFO5       0x00200620

> +#define DATA_IN_ENDPOINT_TX_FIFO6       0x00200640

> +#define DATA_IN_ENDPOINT_TX_FIFO7       0x00200680

> +#define DATA_IN_ENDPOINT_TX_FIFO8       0x002006A0

> +#define DATA_IN_ENDPOINT_TX_FIFO9       0x002006C0

> +#define DATA_IN_ENDPOINT_TX_FIFO10      0x002006E0

> +#define DATA_IN_ENDPOINT_TX_FIFO11      0x00200700

> +#define DATA_IN_ENDPOINT_TX_FIFO12      0x00200720

> +#define DATA_IN_ENDPOINT_TX_FIFO13      0x00200740

> +#define DATA_IN_ENDPOINT_TX_FIFO14      0x00200760

> +#define DATA_IN_ENDPOINT_TX_FIFO15      0x00200F00

> +

> +/*DWC_OTG regsiter descriptor*/

> +/*Device mode CSR MAP*/

> +#define DEVICE_CSR_BASE                 0x800

> +/*Device mode CSR MAP*/

> +#define DEVICE_INEP_BASE                0x900

> +/*Device mode CSR MAP*/

> +#define DEVICE_OUTEP_BASE               0xB00

> +

> +/*** OTG LINK CORE REGISTERS ***/

> +/* Core Global Registers */

> +#define GOTGCTL                         0x000

> +#define GOTGINT                         0x004

> +#define GAHBCFG                         0x008

> +#define GAHBCFG_P_TXF_EMP_LVL           (1 << 8)

> +#define GAHBCFG_NP_TXF_EMP_LVL          (1 << 7)

> +#define GAHBCFG_DMA_EN                  (1 << 5)

> +#define GAHBCFG_GLBL_INTR_EN            (1 << 0)

> +#define GAHBCFG_CTRL_MASK               (GAHBCFG_P_TXF_EMP_LVL | \

> +                                         GAHBCFG_NP_TXF_EMP_LVL | \

> +                                         GAHBCFG_DMA_EN | \

> +                                         GAHBCFG_GLBL_INTR_EN)

> +

> +#define GUSBCFG                         0x00C

> +#define GUSBCFG_USBTRDTIM_8BIT          (0x9 << 10)

> +#define GUSBCFG_USBTRDTIM_16BIT         (0x5 << 10)

> +

> +#define GRSTCTL                         0x010

> +#define GRSTCTL_AHBIDLE                 (1 << 31)

> +#define GRSTCTL_CSFTRST                 (1 << 0)

> +

> +#define GINTSTS                         0x014

> +#define GINTSTS_WKUPINT                 BIT31

> +#define GINTSTS_SESSREGINT              BIT30

> +#define GINTSTS_DISCONNINT              BIT29

> +#define GINTSTS_CONIDSTSCHNG            BIT28

> +#define GINTSTS_LPMTRANRCVD             BIT27

> +#define GINTSTS_PTXFEMP                 BIT26

> +#define GINTSTS_HCHINT                  BIT25

> +#define GINTSTS_PRTINT                  BIT24

> +#define GINTSTS_RESETDET                BIT23

> +#define GINTSTS_FET_SUSP                BIT22

> +#define GINTSTS_INCOMPL_IP              BIT21

> +#define GINTSTS_INCOMPL_SOIN            BIT20

> +#define GINTSTS_OEPINT                  BIT19

> +#define GINTSTS_IEPINT                  BIT18

> +#define GINTSTS_EPMIS                   BIT17

> +#define GINTSTS_RESTOREDONE             BIT16

> +#define GINTSTS_EOPF                    BIT15

> +#define GINTSTS_ISOUTDROP               BIT14

> +#define GINTSTS_ENUMDONE                BIT13

> +#define GINTSTS_USBRST                  BIT12

> +#define GINTSTS_USBSUSP                 BIT11

> +#define GINTSTS_ERLYSUSP                BIT10

> +#define GINTSTS_I2CINT                  BIT9

> +#define GINTSTS_ULPI_CK_INT             BIT8

> +#define GINTSTS_GOUTNAKEFF              BIT7

> +#define GINTSTS_GINNAKEFF               BIT6

> +#define GINTSTS_NPTXFEMP                BIT5

> +#define GINTSTS_RXFLVL                  BIT4

> +#define GINTSTS_SOF                     BIT3

> +#define GINTSTS_OTGINT                  BIT2

> +#define GINTSTS_MODEMIS                 BIT1

> +#define GINTSTS_CURMODE_HOST            BIT0

> +

> +#define GINTMSK                         0x018

> +#define GRXSTSR                         0x01C

> +#define GRXSTSP                         0x020

> +#define GRXFSIZ                         0x024

> +#define GNPTXFSIZ                       0x028

> +#define GNPTXSTS                        0x02C

> +

> +#define GHWCFG1                         0x044

> +#define GHWCFG2                         0x048

> +#define GHWCFG3                         0x04c

> +#define GHWCFG4                         0x050

> +#define GLPMCFG                         0x054

> +

> +#define GDFIFOCFG                       0x05c

> +

> +#define HPTXFSIZ                        0x100

> +#define DIEPTXF(x)                      (0x100 + 4 * (x))


Why 4 *?
Is this a sizeof (UINT32)?

> +#define DIEPTXF1                        0x104

> +#define DIEPTXF2                        0x108

> +#define DIEPTXF3                        0x10C

> +#define DIEPTXF4                        0x110

> +#define DIEPTXF5                        0x114

> +#define DIEPTXF6                        0x118

> +#define DIEPTXF7                        0x11C

> +#define DIEPTXF8                        0x120

> +#define DIEPTXF9                        0x124

> +#define DIEPTXF10                       0x128

> +#define DIEPTXF11                       0x12C

> +#define DIEPTXF12                       0x130

> +#define DIEPTXF13                       0x134

> +#define DIEPTXF14                       0x138

> +#define DIEPTXF15                       0x13C

> +

> +/*** HOST MODE REGISTERS ***/

> +/* Host Global Registers */

> +#define HCFG                            0x400

> +#define HFIR                            0x404

> +#define HFNUM                           0x408

> +#define HPTXSTS                         0x410

> +#define HAINT                           0x414

> +#define HAINTMSK                        0x418

> +

> +/* Host Port Control and Status Registers */

> +#define HPRT                            0x440

> +

> +/* Host Channel-Specific Registers */

> +#define HCCHAR(x)                       (0x500 + 0x20 * (x))

> +#define HCSPLT(x)                       (0x504 + 0x20 * (x))

> +#define HCINT(x)                        (0x508 + 0x20 * (x))

> +#define HCINTMSK(x)                     (0x50C + 0x20 * (x))

> +#define HCTSIZ(x)                       (0x510 + 0x20 * (x))

> +#define HCDMA(x)                        (0x514 + 0x20 * (x))


Why 0x20 *?
CHANNEL_REGISTER_BANK_SIZE?

> +#define HCCHAR0                         0x500

> +#define HCSPLT0                         0x504

> +#define HCINT0                          0x508

> +#define HCINTMSK0                       0x50C

> +#define HCTSIZ0                         0x510

> +#define HCDMA0                          0x514

> +#define HCCHAR1                         0x520

> +#define HCSPLT1                         0x524

> +#define HCINT1                          0x528

> +#define HCINTMSK1                       0x52C

> +#define HCTSIZ1                         0x530

> +#define HCDMA1                          0x534

> +#define HCCHAR2                         0x540

> +#define HCSPLT2                         0x544

> +#define HCINT2                          0x548

> +#define HCINTMSK2                       0x54C

> +#define HCTSIZ2                         0x550

> +#define HCDMA2                          0x554

> +#define HCCHAR3                         0x560

> +#define HCSPLT3                         0x564

> +#define HCINT3                          0x568

> +#define HCINTMSK3                       0x56C

> +#define HCTSIZ3                         0x570

> +#define HCDMA3                          0x574

> +#define HCCHAR4                         0x580

> +#define HCSPLT4                         0x584

> +#define HCINT4                          0x588

> +#define HCINTMSK4                       0x58C

> +#define HCTSIZ4                         0x590

> +#define HCDMA4                          0x594

> +#define HCCHAR5                         0x5A0

> +#define HCSPLT5                         0x5A4

> +#define HCINT5                          0x5A8

> +#define HCINTMSK5                       0x5AC

> +#define HCTSIZ5                         0x5B0

> +#define HCDMA5                          0x5B4

> +#define HCCHAR6                         0x5C0

> +#define HCSPLT6                         0x5C4

> +#define HCINT6                          0x5C8

> +#define HCINTMSK6                       0x5CC

> +#define HCTSIZ6                         0x5D0

> +#define HCDMA6                          0x5D4

> +#define HCCHAR7                         0x5E0

> +#define HCSPLT7                         0x5E4

> +#define HCINT7                          0x5E8

> +#define HCINTMSK7                       0x5EC

> +#define HCTSIZ7                         0x5F0

> +#define HCDMA7                          0x5F4

> +#define HCCHAR8                         0x600

> +#define HCSPLT8                         0x604

> +#define HCINT8                          0x608

> +#define HCINTMSK8                       0x60C

> +#define HCTSIZ8                         0x610

> +#define HCDMA8                          0x614

> +#define HCCHAR9                         0x620

> +#define HCSPLT9                         0x624

> +#define HCINT9                          0x628

> +#define HCINTMSK9                       0x62C

> +#define HCTSIZ9                         0x630

> +#define HCDMA9                          0x634

> +#define HCCHAR10                        0x640

> +#define HCSPLT10                        0x644

> +#define HCINT10                         0x648

> +#define HCINTMSK10                      0x64C

> +#define HCTSIZ10                        0x650

> +#define HCDMA10                         0x654

> +#define HCCHAR11                        0x660

> +#define HCSPLT11                        0x664

> +#define HCINT11                         0x668

> +#define HCINTMSK11                      0x66C

> +#define HCTSIZ11                        0x670

> +#define HCDMA11                         0x674

> +#define HCCHAR12                        0x680

> +#define HCSPLT12                        0x684

> +#define HCINT12                         0x688

> +#define HCINTMSK12                      0x68C

> +#define HCTSIZ12                        0x690

> +#define HCDMA12                         0x694

> +#define HCCHAR13                        0x6A0

> +#define HCSPLT13                        0x6A4

> +#define HCINT13                         0x6A8

> +#define HCINTMSK13                      0x6AC

> +#define HCTSIZ13                        0x6B0

> +#define HCDMA13                         0x6B4

> +#define HCCHAR14                        0x6C0

> +#define HCSPLT14                        0x6C4

> +#define HCINT14                         0x6C8

> +#define HCINTMSK14                      0x6CC

> +#define HCTSIZ14                        0x6D0

> +#define HCDMA14                         0x6D4

> +#define HCCHAR15                        0x6E0

> +#define HCSPLT15                        0x6E4

> +#define HCINT15                         0x6E8

> +#define HCINTMSK15                      0x6EC

> +#define HCTSIZ15                        0x6F0

> +#define HCDMA15                         0x6F4


Why does this hold both the macros to calculate the offsets for a
given channel and all of the absolute register offsets per channel?

> +

> +/*** DEVICE MODE REGISTERS ***/

> +/* Device Global Registers */

> +#define DCFG                            0x800

> +#define DCFG_DESCDMA                    BIT23

> +#define DCFG_EPMISCNT_MASK              (0x1F << 18)

> +#define DCFG_EPMISCNT_SHIFT             18

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

> +#define DCFG_DEVADDR_SHIFT              4

> +#define DCFG_DEVADDR(x)                 (((x) << DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK)

> +#define DCFG_NZ_STS_OUT_HSHK            BIT2

> +

> +#define DCTL                            0x804

> +#define DCTL_PWRONPRGDONE               BIT11

> +#define DCTL_GNPINNAKSTS                BIT2

> +#define DCTL_SFTDISCON                  BIT1

> +

> +#define DSTS                            0x808

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

> +#define DSTS_ENUMSPD_HIGH               (0 << 1)

> +#define DSTS_ENUMSPD_FULL               (1 << 1)

> +

> +#define DIEPMSK                         0x810

> +#define DOEPMSK                         0x814

> +

> +#define DXEPMSK_TIMEOUTMSK              BIT3

> +#define DXEPMSK_AHBERMSK                BIT2

> +#define DXEPMSK_XFERCOMPLMSK            BIT0

> +

> +#define DAINT                           0x818

> +#define DAINTMSK                        0x81C

> +

> +#define DAINTMSK_OUTEPMSK_SHIFT         16

> +#define DAINTMSK_INEPMSK_SHIFT          0

> +

> +#define DTKNQR1                         0x820

> +#define DTKNQR2                         0x824

> +#define DVBUSDIS                        0x828

> +#define DVBUSPULSE                      0x82C

> +#define DTHRCTL                         0x830

> +

> +/* Device Logical IN Endpoint-Specific Registers */

> +#define DIEPCTL(x)                      (0x900 + 0x20 * (x))

> +#define DIEPINT(x)                      (0x908 + 0x20 * (x))

> +#define DIEPTSIZ(x)                     (0x910 + 0x20 * (x))

> +#define DIEPDMA(x)                      (0x914 + 0x20 * (x))

> +#define DTXFSTS(x)                      (0x918 + 0x20 * (x))


Same again - please add a #define for that 0x20.

> +

> +#define DIEPCTL0                        0x900

> +#define DIEPINT0                        0x908

> +#define DIEPTSIZ0                       0x910

> +#define DIEPDMA0                        0x914

> +#define DIEPCTL1                        0x920

> +#define DIEPINT1                        0x928

> +#define DIEPTSIZ1                       0x930

> +#define DIEPDMA1                        0x934

> +#define DIEPCTL2                        0x940

> +#define DIEPINT2                        0x948

> +#define DIEPTSIZ2                       0x950

> +#define DIEPDMA2                        0x954

> +#define DIEPCTL3                        0x960

> +#define DIEPINT3                        0x968

> +#define DIEPTSIZ3                       0x970

> +#define DIEPDMA3                        0x974

> +#define DIEPCTL4                        0x980

> +#define DIEPINT4                        0x988

> +#define DIEPTSIZ4                       0x990

> +#define DIEPDMA4                        0x994

> +#define DIEPCTL5                        0x9A0

> +#define DIEPINT5                        0x9A8

> +#define DIEPTSIZ5                       0x9B0

> +#define DIEPDMA5                        0x9B4

> +#define DIEPCTL6                        0x9C0

> +#define DIEPINT6                        0x9C8

> +#define DIEPTSIZ6                       0x9D0

> +#define DIEPDMA6                        0x9D4

> +#define DIEPCTL7                        0x9E0

> +#define DIEPINT7                        0x9E8

> +#define DIEPTSIZ7                       0x9F0

> +#define DIEPDMA7                        0x9F4

> +#define DIEPCTL8                        0xA00

> +#define DIEPINT8                        0xA08

> +#define DIEPTSIZ8                       0xA10

> +#define DIEPDMA8                        0xA14

> +#define DIEPCTL9                        0xA20

> +#define DIEPINT9                        0xA28

> +#define DIEPTSIZ9                       0xA30

> +#define DIEPDMA9                        0xA34

> +#define DIEPCTL10                       0xA40

> +#define DIEPINT10                       0xA48

> +#define DIEPTSIZ10                      0xA50

> +#define DIEPDMA10                       0xA54

> +#define DIEPCTL11                       0xA60

> +#define DIEPINT11                       0xA68

> +#define DIEPTSIZ11                      0xA70

> +#define DIEPDMA11                       0xA74

> +#define DIEPCTL12                       0xA80

> +#define DIEPINT12                       0xA88

> +#define DIEPTSIZ12                      0xA90

> +#define DIEPDMA12                       0xA94

> +#define DIEPCTL13                       0xAA0

> +#define DIEPINT13                       0xAA8

> +#define DIEPTSIZ13                      0xAB0

> +#define DIEPDMA13                       0xAB4

> +#define DIEPCTL14                       0xAC0

> +#define DIEPINT14                       0xAC8

> +#define DIEPTSIZ14                      0xAD0

> +#define DIEPDMA14                       0xAD4

> +#define DIEPCTL15                       0xAE0

> +#define DIEPINT15                       0xAE8

> +#define DIEPTSIZ15                      0xAF0

> +#define DIEPDMA15                       0xAF4


And again, why do we have both macros and all of the possible combinations?

> +

> +/* Device Logical OUT Endpoint-Specific Registers */

> +#define DOEPCTL(x)                      (0xB00 + 0x20 * (x))

> +#define DOEPINT(x)                      (0xB08 + 0x20 * (x))

> +#define DOEPTSIZ(x)                     (0xB10 + 0x20 * (x))

> +

> +#define DXEPINT_EPDISBLD                BIT1

> +#define DXEPINT_XFERCOMPL               BIT0

> +

> +#define DXEPTSIZ_SUPCNT(x)              (((x) & 0x3) << 29)

> +#define DXEPTSIZ_PKTCNT(x)              (((x) & 0x3) << 19)

> +#define DXEPTSIZ_XFERSIZE(x)            ((x) & 0x7F)

> +

> +#define DOEPDMA(x)                      (0xB14 + 0x20 * (x))


Move this up to below DOEPTSIZ?
Delete all of the below definitions and use the macros instead
And a #define for that 0x20?

> +#define DOEPCTL0                        0xB00

> +#define DOEPINT0                        0xB08

> +#define DOEPTSIZ0                       0xB10

> +#define DOEPDMA0                        0xB14

> +#define DOEPCTL1                        0xB20

> +#define DOEPINT1                        0xB28

> +#define DOEPTSIZ1                       0xB30

> +#define DOEPDMA1                        0xB34

> +#define DOEPCTL2                        0xB40

> +#define DOEPINT2                        0xB48

> +#define DOEPTSIZ2                       0xB50

> +#define DOEPDMA2                        0xB54

> +#define DOEPCTL3                        0xB60

> +#define DOEPINT3                        0xB68

> +#define DOEPTSIZ3                       0xB70

> +#define DOEPDMA3                        0xB74

> +#define DOEPCTL4                        0xB80

> +#define DOEPINT4                        0xB88

> +#define DOEPTSIZ4                       0xB90

> +#define DOEPDMA4                        0xB94

> +#define DOEPCTL5                        0xBA0

> +#define DOEPINT5                        0xBA8

> +#define DOEPTSIZ5                       0xBB0

> +#define DOEPDMA5                        0xBB4

> +#define DOEPCTL6                        0xBC0

> +#define DOEPINT6                        0xBC8

> +#define DOEPTSIZ6                       0xBD0

> +#define DOEPDMA6                        0xBD4

> +#define DOEPCTL7                        0xBE0

> +#define DOEPINT7                        0xBE8

> +#define DOEPTSIZ7                       0xBF0

> +#define DOEPDMA7                        0xBF4

> +#define DOEPCTL8                        0xC00

> +#define DOEPINT8                        0xC08

> +#define DOEPTSIZ8                       0xC10

> +#define DOEPDMA8                        0xC14

> +#define DOEPCTL9                        0xC20

> +#define DOEPINT9                        0xC28

> +#define DOEPTSIZ9                       0xC30

> +#define DOEPDMA9                        0xC34

> +#define DOEPCTL10                       0xC40

> +#define DOEPINT10                       0xC48

> +#define DOEPTSIZ10                      0xC50

> +#define DOEPDMA10                       0xC54

> +#define DOEPCTL11                       0xC60

> +#define DOEPINT11                       0xC68

> +#define DOEPTSIZ11                      0xC70

> +#define DOEPDMA11                       0xC74

> +#define DOEPCTL12                       0xC80

> +#define DOEPINT12                       0xC88

> +#define DOEPTSIZ12                      0xC90

> +#define DOEPDMA12                       0xC94

> +#define DOEPCTL13                       0xCA0

> +#define DOEPINT13                       0xCA8

> +#define DOEPTSIZ13                      0xCB0

> +#define DOEPDMA13                       0xCB4

> +#define DOEPCTL14                       0xCC0

> +#define DOEPINT14                       0xCC8

> +#define DOEPTSIZ14                      0xCD0

> +#define DOEPDMA14                       0xCD4

> +#define DOEPCTL15                       0xCE0

> +#define DOEPINT15                       0xCE8

> +#define DOEPTSIZ15                      0xCF0

> +#define DOEPDMA15                       0xCF4

> +

> +#define DXEPCTL_EPENA                   BIT31

> +#define DXEPCTL_SNAK                    BIT27

> +#define DXEPCTL_CNAK                    BIT26

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

> +#define DXEPCTL_STALL                   BIT21

> +#define DXEPCTL_EPTYPE_MASK             (BIT19 | BIT18)

> +#define DXEPCTL_EPTYPE(x)               (((x) & 0x3) << 18)

> +#define DXEPCTL_NAKSTS                  BIT17

> +#define DXEPCTL_USBACTEP                BIT15

> +#define DXEPCTL_MPS_MASK                0x7FF

> +

> +#define DXEPTSIZN_PKTCNT_MASK           (0x3FF << 19)

> +#define DXEPTSIZN_PKTCNT(x)             (((x) & 0x3FF) << 19)

> +#define DXEPTSIZN_XFERSIZE_MASK         0x7FFFF

> +#define DXEPTSIZN_XFERSIZE(x)           ((x) & 0x7FFFF)

> +

> +/* Power and Clock Gating Register */

> +#define PCGCCTL                         0xE00

> +

> +#define EP0FIFO                         0x1000

> +

> +/**

> + * This union represents the bit fields in the DMA Descriptor

> + * status quadlet. Read the quadlet into the <i>d32</i> member then

> + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and

> + * <i>b_iso_in</i> elements.

> + */


Drop the HTML formatting please.

> +typedef union {

> +  /** raw register data */

> +  UINT32 d32;

> +    /** quadlet bits */

> +  struct {

> +    /** Received number of bytes */

> +    unsigned bytes:16;

> +    /** NAK bit - only for OUT EPs */

> +    unsigned nak:1;

> +    unsigned reserved17_22:6;

> +    /** Multiple Transfer - only for OUT EPs */

> +    unsigned mtrf:1;

> +    /** Setup Packet received - only for OUT EPs */

> +    unsigned sr:1;

> +    /** Interrupt On Complete */

> +    unsigned ioc:1;

> +    /** Short Packet */

> +    unsigned sp:1;

> +    /** Last */

> +    unsigned l:1;

> +    /** Receive Status */

> +    unsigned sts:2;

> +    /** Buffer Status */

> +    unsigned bs:2;

> +  } b;

> +} DevDmaDescStatus;


This struct does not conform to coding style.

> +

> +/**

> + * DMA Descriptor structure

> + *

> + * DMA Descriptor structure contains two quadlets:

> + * Status quadlet and Data buffer pointer.

> + */

> +typedef struct {

> +  /** DMA Descriptor status quadlet */

> +  DevDmaDescStatus status;

> +  /** DMA Descriptor data buffer pointer */

> +  UINT32 buf;

> +} DwUsbDevDmaDesc;

> +

> +#endif /* __DW_USB_DXE_H__ */

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

> new file mode 100644

> index 000000000000..6e1086190796

> --- /dev/null

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

> @@ -0,0 +1,912 @@

> +/** @file

> +

> +  Copyright (c) 2018, Linaro. All rights reserved.

> +

> +  This program and the accompanying materials are licensed and made available

> +  under the terms and conditions of the BSD License which accompanies this

> +  distribution.  The full text of the license may be found at

> +  http://opensource.org/licenses/bsd-license.php

> +

> +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> +

> +**/

> +

> +#include <IndustryStandard/Usb.h>

> +#include <Library/ArmLib.h>


Hmm?

> +#include <Library/BaseLib.h>

> +#include <Library/BaseMemoryLib.h>

> +#include <Library/CacheMaintenanceLib.h>

> +#include <Library/DebugLib.h>

> +#include <Library/DmaLib.h>

> +#include <Library/IoLib.h>

> +#include <Library/MemoryAllocationLib.h>

> +#include <Library/TimerLib.h>

> +#include <Library/UefiBootServicesTableLib.h>

> +#include <Library/UefiDriverEntryPoint.h>

> +#include <Library/UefiRuntimeServicesTableLib.h>

> +#include <Protocol/DwUsb.h>

> +#include <Protocol/UsbDevice.h>

> +

> +#include "DwUsbDxe.h"

> +

> +#define USB_TYPE_LENGTH               16


What type?

> +#define USB_BLOCK_HIGH_SPEED_SIZE     512


What size?

> +#define DATA_SIZE                     32768


What data?

> +#define CMD_SIZE                      512


What command?

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


This macro is used exactly once. Please just inline the call (with ==
0 instead of !).

> +

> +//

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

> +// 10 Microseconds

> +//

> +#define DW_INTERRUPT_POLL_PERIOD      10000

> +

> +#define ENDPOINT0                     0

> +#define ENDPOINT1                     1

> +

> +#define DIR_OUT                       0

> +#define DIR_IN                        1

> +

> +#define DWUSB_BUFFER_PAGE_NUM         16

> +

> +#define DESCRIPTOR_INDEX_LANG         0

> +#define DESCRIPTOR_INDEX_MANUFACTURER 1

> +#define DESCRIPTOR_INDEX_PRODUCT      2

> +#define DESCRIPTOR_INDEX_SERIALNUMBER 3

> +

> +#define DESCRIPTOR_TYPE(x)            (((x) >> 8) & 0xFF)

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

> +

> +typedef struct {

> +  USB_DEVICE_DESCRIPTOR        *DeviceDescriptor;

> +  USB_CONFIG_DESCRIPTOR        *ConfigDescriptor;

> +} DW_USB_DESCRIPTOR;


Please move everything after my last comment to here into DwUsbDxe.h.
Or DwUsb2Dxe.h, I guess it should be called.

> +

> +EFI_GUID  gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;


Problematic, as mentioned in comment on DwUsb3Dxe.

> +

> +STATIC DwUsbDevDmaDesc  *gDmaDesc,*gDmaDescEp0,*gDmaDescIn;

> +STATIC USB_DEVICE_REQUEST      *gCtrlReq;

> +STATIC VOID                    *RxBuf;

> +STATIC UINTN                   RxDescBytes;

> +STATIC UINTN                   mNumDataBytes;

> +

> +STATIC DW_USB_PROTOCOL         *DwUsb;

> +STATIC DW_USB_DESCRIPTOR       gDwUsbDescriptor;


Please use 'm' prefix on all STATIC globals.

> +

> +STATIC USB_DEVICE_RX_CALLBACK  mDataReceivedCallback;

> +STATIC USB_DEVICE_TX_CALLBACK  mDataSentCallback;

> +

> +

> +/* To detect which mode was run, high speed or full speed */

> +STATIC

> +UINTN

> +UsbDrvPortSpeed (

> +  VOID

> +  )

> +{

> +  return (((READ_REG32 (DSTS) & DSTS_ENUMSPD_MASK) == DSTS_ENUMSPD_HIGH));

> +}

> +

> +STATIC

> +VOID

> +ResetEndpoints (

> +  VOID

> +  )

> +{

> +  UINT32                       Data;

> +

> +  /* EP0 IN ACTIVE NEXT=1 */

> +  WRITE_REG32 (DIEPCTL0, DXEPCTL_USBACTEP | BIT11);

> +

> +  /* EP0 OUT ACTIVE */

> +  WRITE_REG32 (DOEPCTL0, DXEPCTL_USBACTEP);

> +

> +  /* Clear any pending OTG Interrupts */

> +  WRITE_REG32 (GOTGINT, ~0);

> +

> +  /* Clear any pending interrupts */

> +  WRITE_REG32 (GINTSTS, ~0);

> +  WRITE_REG32 (DIEPINT0, ~0);

> +  WRITE_REG32 (DOEPINT0, ~0);

> +  WRITE_REG32 (DIEPINT1, ~0);

> +  WRITE_REG32 (DOEPINT1, ~0);

> +

> +  /* IN EP interrupt mask */

> +  WRITE_REG32 (DIEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);

> +  /* OUT EP interrupt mask */

> +  WRITE_REG32 (DOEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);

> +  /* Enable interrupts on EndPoint0 */

> +  WRITE_REG32 (DAINTMSK, (1 << DAINTMSK_OUTEPMSK_SHIFT) | (1 << DAINTMSK_INEPMSK_SHIFT));

> +

> +  /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/

> +  WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));


Long lines above.

> +

> +  //

> +  //notes that:the compulsive conversion is expectable.


What does this mean?

> +  //

> +  gDmaDescEp0->status.b.bs = 0x3;

> +  gDmaDescEp0->status.b.mtrf = 0;

> +  gDmaDescEp0->status.b.sr = 0;

> +  gDmaDescEp0->status.b.l = 1;

> +  gDmaDescEp0->status.b.ioc = 1;

> +  gDmaDescEp0->status.b.sp = 0;

> +  gDmaDescEp0->status.b.bytes = 64;

> +  gDmaDescEp0->buf = (UINT32)(UINTN)gCtrlReq;

> +  gDmaDescEp0->status.b.sts = 0;

> +  gDmaDescEp0->status.b.bs = 0x0;


What do all of these live-coded values mean?
Need #defines or possibly comments.

> +  WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)gDmaDescEp0);

> +  /* EP0 OUT ENABLE CLEARNAK */

> +  Data = READ_REG32 (DOEPCTL0);

> +  WRITE_REG32 (DOEPCTL0, Data | DXEPCTL_EPENA | DXEPCTL_CNAK);

> +}

> +

> +STATIC

> +VOID

> +EndPointTx (

> +  IN UINT8          EndPoint,

> +  IN CONST VOID    *Ptr,

> +  IN UINTN          Len

> +  )

> +{

> +  UINT32            BlockSize;

> +  UINT32            Packets;

> +  UINT32            Data;

> +

> +  /* EPx OUT ACTIVE */

> +  Data = READ_REG32 (DIEPCTL (EndPoint));

> +  WRITE_REG32 (DIEPCTL (EndPoint), Data | DXEPCTL_USBACTEP);

> +  if (!EndPoint) {

> +      BlockSize = 64;

> +  } else {

> +      BlockSize = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;


I will want #defines for those 64.
Among other things that will tell me if it's the same 64 or whether
they happen to have the same numeric value.

> +  }

> +  Packets = (Len + BlockSize - 1) / BlockSize;

> +

> +  if (!Len) {

> +    /* send one empty packet */

> +    gDmaDescIn->status.b.bs = 0x3;

> +    gDmaDescIn->status.b.l = 1;

> +    gDmaDescIn->status.b.ioc = 1;

> +    gDmaDescIn->status.b.sp = 1;

> +    gDmaDescIn->status.b.bytes = 0;

> +    gDmaDescIn->buf = 0;

> +    gDmaDescIn->status.b.sts = 0;

> +    gDmaDescIn->status.b.bs = 0x0;


#defines and/or comments for numbers.

> +

> +    WRITE_REG32 (DIEPDMA (EndPoint), (UINT32)(UINTN)gDmaDescIn);             // DMA Address (DMAAddr) is zero

> +  } else {

> +    WRITE_REG32 (DIEPTSIZ (EndPoint), Len | DXEPTSIZN_PKTCNT (Packets));

> +

> +    //

> +    //flush cache

> +    //

> +    WriteBackDataCacheRange ((VOID *)Ptr, Len);

> +

> +    gDmaDescIn->status.b.bs = 0x3;

> +    gDmaDescIn->status.b.l = 1;

> +    gDmaDescIn->status.b.ioc = 1;

> +    gDmaDescIn->status.b.sp = 1;

> +    gDmaDescIn->status.b.bytes = Len;

> +    gDmaDescIn->buf = (UINT32)(UINTN)Ptr;

> +    gDmaDescIn->status.b.sts = 0;

> +    gDmaDescIn->status.b.bs = 0x0;


#defines and/or comments for numbers.

> +    WRITE_REG32 (DIEPDMA (EndPoint), (UINT32)(UINTN)gDmaDescIn);         // Ptr is DMA address

> +  }

> +  ArmDataSynchronizationBarrier ();


MemoryFence ()?

> +  /* epena & cnak */

> +  Data = READ_REG32 (DIEPCTL (EndPoint));

> +  WRITE_REG32 (DIEPCTL (EndPoint), Data | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11);

> +}

> +

> +STATIC

> +VOID

> +EndPointRx (

> +  IN UINTN            EndPoint,

> +  IN UINTN            Len

> +  )

> +{

> +  UINT32              Data;

> +

> +  /* EPx UNSTALL */

> +  Data = READ_REG32 (DOEPCTL (EndPoint));

> +  WRITE_REG32 (DOEPCTL (EndPoint), Data & ~DXEPCTL_STALL);

> +  /* EPx OUT ACTIVE */

> +  Data = READ_REG32 (DOEPCTL (EndPoint));

> +  WRITE_REG32 (DOEPCTL (EndPoint), Data | DXEPCTL_USBACTEP);

> +

> +  if (Len >= DATA_SIZE) {

> +    RxDescBytes = DATA_SIZE;

> +  } else {

> +    RxDescBytes = Len;

> +  }

> +

> +  RxBuf = AllocatePool (DATA_SIZE);

> +  if (RxBuf == NULL) {

> +    DEBUG ((DEBUG_ERROR, "EndPointRx: failed to allocate buffer\n"));

> +    return;

> +  }

> +

> +  InvalidateDataCacheRange (RxBuf, Len);

> +

> +  gDmaDesc->status.b.bs = 0x3;

> +  gDmaDesc->status.b.mtrf = 0;

> +  gDmaDesc->status.b.sr = 0;

> +  gDmaDesc->status.b.l = 1;

> +  gDmaDesc->status.b.ioc = 1;

> +  gDmaDesc->status.b.sp = 0;

> +  gDmaDesc->status.b.bytes = (UINT32)RxDescBytes;

> +  gDmaDesc->buf = (UINT32)(UINTN)RxBuf;

> +  gDmaDesc->status.b.sts = 0;

> +  gDmaDesc->status.b.bs = 0x0;


#defines and/or comments for numbers.

> +

> +  ArmDataSynchronizationBarrier ();


MemoryFence ()?

> +  WRITE_REG32 (DOEPDMA (EndPoint), (UINT32)(UINTN)gDmaDesc);

> +  /* EPx OUT ENABLE CLEARNAK */

> +  Data = READ_REG32 (DOEPCTL (EndPoint));

> +  WRITE_REG32 (DOEPCTL (EndPoint), Data | DXEPCTL_EPENA | DXEPCTL_CNAK);

> +}

> +

> +STATIC

> +EFI_STATUS

> +HandleGetDescriptor (

> +  IN USB_DEVICE_REQUEST  *Request

> +  )

> +{

> +  UINTN                             ResponseSize;

> +  VOID                             *ResponseData;

> +  EFI_USB_STRING_DESCRIPTOR        *Descriptor = NULL;

> +  UINTN                             DescriptorSize;

> +

> +  ResponseSize = 0;

> +  ResponseData = NULL;

> +

> +  // Pretty confused if bmRequestType is anything but this:

> +  if (Request->RequestType != USB_DEV_GET_DESCRIPTOR_REQ_TYPE) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  //

> +  // Choose the response

> +  //

> +  switch (DESCRIPTOR_TYPE(Request->Value)) {

> +  case USB_DESC_TYPE_DEVICE:

> +    DEBUG ((DEBUG_INFO, "DwUsbDxe: Got a request for device descriptor\n"));

> +    ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);

> +    ResponseData = gDwUsbDescriptor.DeviceDescriptor;

> +    break;

> +  case USB_DESC_TYPE_CONFIG:

> +    DEBUG ((DEBUG_INFO, "DwUsbDxe: Got a request for config descriptor\n"));

> +    ResponseSize = gDwUsbDescriptor.ConfigDescriptor->TotalLength;

> +    ResponseData = gDwUsbDescriptor.ConfigDescriptor;

> +    break;

> +  case USB_DESC_TYPE_STRING:

> +    DEBUG ((

> +      DEBUG_INFO,

> +      "DwUsbDxe: Got a request for String descriptor %d\n",

> +      Request->Value & 0xFF

> +      ));

> +    switch (DESCRIPTOR_INDEX(Request->Value)) {


Put the nested switch in a separate function, this is unreadable.

> +    case 0:

> +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +

> +                       (LANG_LENGTH + 1) * sizeof (CHAR16);

> +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);

> +      if (Descriptor == NULL) {

> +        return EFI_OUT_OF_RESOURCES;

> +      }

> +      Descriptor->Length = LANG_LENGTH * sizeof (CHAR16);

> +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;

> +      DwUsb->GetLang (Descriptor->String, &Descriptor->Length);

> +      ResponseSize = Descriptor->Length;

> +      ResponseData = Descriptor;

> +      break;

> +    case 1:

> +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +

> +                       (MANU_FACTURER_STRING_LENGTH + 1) * sizeof (CHAR16);

> +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);

> +      if (Descriptor == NULL) {

> +        return EFI_OUT_OF_RESOURCES;

> +      }

> +      Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);

> +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;

> +      DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length);

> +      ResponseSize = Descriptor->Length;

> +      ResponseData = Descriptor;

> +      break;

> +    case 2:

> +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +

> +                       (PRODUCT_STRING_LENGTH + 1) * sizeof (CHAR16);

> +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);

> +      if (Descriptor == NULL) {

> +        return EFI_OUT_OF_RESOURCES;

> +      }

> +      Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16);

> +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;

> +      DwUsb->GetProduct (Descriptor->String, &Descriptor->Length);

> +      ResponseSize = Descriptor->Length;

> +      ResponseData = Descriptor;

> +      break;

> +    case 3:

> +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +

> +                       SERIAL_STRING_LENGTH * sizeof (CHAR16) + 1;

> +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);

> +      if (Descriptor == NULL) {

> +        return EFI_OUT_OF_RESOURCES;

> +      }

> +      Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16);

> +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;

> +      DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length);

> +      ResponseSize = Descriptor->Length;

> +      ResponseData = Descriptor;

> +      break;

> +    }

> +    break;

> +  default:

> +    DEBUG ((

> +      DEBUG_INFO,

> +      "DwUsbDxe: Didn't understand request for descriptor 0x%04x\n",

> +      Request->Value

> +      ));

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  //

> +  // Send the response

> +  //

> +  if (Request->Length < ResponseSize) {

> +    //

> +    // Truncate response

> +    //

> +    ResponseSize = Request->Length;

> +  } else if (Request->Length > ResponseSize) {

> +    DEBUG ((DEBUG_INFO, "DwUsbDxe: Info: ResponseSize < wLength\n"));

> +  }

> +

> +  EndPointTx (ENDPOINT0, ResponseData, ResponseSize);

> +  if (Descriptor) {

> +    FreePool (Descriptor);

> +  }

> +

> +  return EFI_SUCCESS;

> +}

> +

> +STATIC

> +EFI_STATUS

> +HandleSetAddress (

> +  IN USB_DEVICE_REQUEST  *Request

> +  )

> +{

> +  UINT32                 Data;

> +

> +  //

> +  // Pretty confused if bmRequestType is anything but this:

> +  //

> +  if (Request->RequestType != USB_DEV_SET_ADDRESS_REQ_TYPE) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +  DEBUG ((DEBUG_INFO, "DwUsbDxe: Setting address to %d\n", Request->Value));

> +  ResetEndpoints ();

> +

> +  Data = READ_REG32 (DCFG);

> +  Data &= ~DCFG_DEVADDR_MASK;

> +  Data |= DCFG_DEVADDR (Request->Value);

> +  WRITE_REG32 (DCFG, Data);

> +  EndPointTx (ENDPOINT0, NULL, 0);

> +

> +  return EFI_SUCCESS;

> +}

> +

> +STATIC

> +VOID

> +UsbDrvRequestEndpoint (

> +  IN UINTN           Type,

> +  IN UINTN           Dir

> +  )

> +{

> +  UINTN              EndPoint = 1;

> +  UINTN              NewBits;

> +  UINT32             Data;

> +

> +  NewBits = DXEPCTL_EPTYPE (Type) | BIT28;

> +

> +  /*

> +   * (Type << 18):Endpoint Type (EPType)

> +   * 0x10000000:Endpoint Enable (EPEna)

> +   * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.

> +   * (ep<<22):TxFIFO Number (TxFNum)

> +   * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.

> +   */

> +  if (Dir == DIR_IN) {  // IN: to host

> +    Data = READ_REG32 (DIEPCTL (EndPoint));

> +    Data &= ~DXEPCTL_EPTYPE_MASK;

> +    Data |= NewBits | DXEPCTL_TXFNUM (EndPoint) | DXEPCTL_NAKSTS;

> +    WRITE_REG32 (DIEPCTL (EndPoint), Data);

> +  } else {    // OUT: to device

> +    Data = READ_REG32 (DOEPCTL (EndPoint));

> +    Data &= ~DXEPCTL_EPTYPE_MASK;

> +    Data |= NewBits;

> +    WRITE_REG32 (DOEPCTL (EndPoint), Data);

> +  }

> +}

> +

> +STATIC

> +EFI_STATUS

> +HandleSetConfiguration (

> +  IN USB_DEVICE_REQUEST  *Request

> +  )

> +{

> +  UINT32                 Data;

> +

> +  if (Request->RequestType != USB_DEV_SET_CONFIGURATION_REQ_TYPE) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  //

> +  // Cancel all transfers

> +  //

> +  ResetEndpoints ();

> +

> +  UsbDrvRequestEndpoint (2, DIR_OUT);

> +  UsbDrvRequestEndpoint (2, DIR_IN);


What is 2?

> +

> +  Data = READ_REG32 (DIEPCTL1);

> +  WRITE_REG32 (DIEPCTL1, Data | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11);


Please give #defines for those named bits (or the whole command if
more appropriate).

> +

> +  /* Enable interrupts on all endpoints */

> +  WRITE_REG32 (DAINTMSK, ~0);

> +

> +  EndPointRx (ENDPOINT1, CMD_SIZE);

> +  EndPointTx (ENDPOINT0, NULL, 0);

> +  return EFI_SUCCESS;

> +}

> +

> +

> +STATIC

> +EFI_STATUS

> +HandleDeviceRequest (

> +  IN USB_DEVICE_REQUEST  *Request

> +  )

> +{

> +  EFI_STATUS  Status;

> +

> +  switch (Request->Request) {

> +  case USB_DEV_GET_DESCRIPTOR:

> +    Status = HandleGetDescriptor (Request);

> +    break;

> +  case USB_DEV_SET_ADDRESS:

> +    Status = HandleSetAddress (Request);

> +    break;

> +  case USB_DEV_SET_CONFIGURATION:

> +    Status = HandleSetConfiguration (Request);

> +    break;

> +  default:

> +    DEBUG ((DEBUG_ERROR,

> +      "Didn't understand RequestType 0x%x Request 0x%x\n",

> +      Request->RequestType, Request->Request));

> +      Status = EFI_INVALID_PARAMETER;

> +    break;

> +  }

> +

> +  return Status;

> +}

> +

> +STATIC

> +VOID

> +HandleEndPointInEvent (

> +  VOID

> +  )

> +{

> +  UINT32              EndPointInts;

> +

> +  EndPointInts = READ_REG32 (DIEPINT0);

> +  WRITE_REG32 (DIEPINT0, EndPointInts);

> +  if (EndPointInts & DXEPINT_XFERCOMPL) {

> +    DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0)));

> +  }

> +

> +  EndPointInts = READ_REG32 (DIEPINT1);

> +  WRITE_REG32 (DIEPINT1, EndPointInts);

> +  if (EndPointInts & DXEPINT_XFERCOMPL) {

> +    DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n"));

> +  }

> +}

> +

> +STATIC

> +VOID

> +HandleEndPointOutEvent (

> +  VOID

> +  )

> +{

> +  UINT32              EndPointInts;

> +  UINT32              Data;

> +

> +  /*

> +   * indicates the status of an endpoint

> +   * with respect to USB- and AHB-related events.

> +   */

> +  EndPointInts = READ_REG32 (DOEPINT0);

> +  if (EndPointInts) {

> +    WRITE_REG32 (DOEPINT0, EndPointInts);

> +    if (EndPointInts & DXEPINT_XFERCOMPL) {

> +      DEBUG ((DEBUG_INFO, "INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32 (DOEPTSIZ0)));

> +    }

> +    /*

> +     *

> +     * IN Token Received When TxFIFO is Empty (INTknTXFEmp)

> +     * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)

> +     * was empty. This interrupt is asserted on the endpoint for which the IN token

> +     * was received.

> +     */

> +    if (EndPointInts & BIT3) { /* SETUP phase done */


What is BIT3?

> +      Data = READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK;

> +      WRITE_REG32 (DIEPCTL0, Data);

> +      Data = READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK;

> +      WRITE_REG32 (DOEPCTL0, Data);

> +      /* clear IN EP intr */

> +      WRITE_REG32 (DIEPINT0, ~0);

> +      HandleDeviceRequest((USB_DEVICE_REQUEST *)gCtrlReq);

> +    }

> +

> +    /* Make sure EP0 OUT is set up to accept the next request */

> +    WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));

> +    /*

> +     * IN Token Received When TxFIFO is Empty (INTknTXFEmp)

> +     * Indicates that an IN token was received when the associated

> +     * TxFIFO (periodic/nonperiodic) * was empty. This interrupt is

> +     * asserted on the endpoint for which the IN token was received.

> +     */

> +    gDmaDescEp0->status.b.bs = 0x3;

> +    gDmaDescEp0->status.b.mtrf = 0;

> +    gDmaDescEp0->status.b.sr = 0;

> +    gDmaDescEp0->status.b.l = 1;

> +    gDmaDescEp0->status.b.ioc = 1;

> +    gDmaDescEp0->status.b.sp = 0;

> +    gDmaDescEp0->status.b.bytes = 64;

> +    gDmaDescEp0->buf = (UINT32)(UINTN)gCtrlReq;

> +    gDmaDescEp0->status.b.sts = 0;

> +    gDmaDescEp0->status.b.bs = 0x0;


Need some #defines for those numbers.

> +    WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)gDmaDescEp0);

> +    //

> +    // endpoint enable; clear NAK

> +    //

> +    WRITE_REG32 (DOEPCTL0, DXEPCTL_EPENA | DXEPCTL_CNAK);

> +  }

> +

> +  EndPointInts = (READ_REG32 (DOEPINT1));

> +  if (EndPointInts) {

> +    WRITE_REG32 (DOEPINT1, EndPointInts);

> +    /* Transfer Completed Interrupt (XferCompl);Transfer completed */

> +    if (EndPointInts & DXEPINT_XFERCOMPL) {

> +

> +      UINTN Bytes = RxDescBytes - gDmaDesc->status.b.bytes;

> +      UINTN Len = 0;

> +

> +      ArmDataSynchronizationBarrier ();


MemoryFence ()?

> +      if (MATCH_CMD_LITERAL ("download", RxBuf)) {

> +        mNumDataBytes = AsciiStrHexToUint64 (RxBuf + sizeof ("download"));

> +      } else {

> +        if (mNumDataBytes != 0) {

> +          mNumDataBytes -= Bytes;

> +        }

> +      }

> +

> +      mDataReceivedCallback (Bytes, RxBuf);

> +

> +      if (mNumDataBytes == 0) {

> +        Len = CMD_SIZE;

> +      } else if (mNumDataBytes > DATA_SIZE) {

> +        Len = DATA_SIZE;

> +      } else {

> +        Len = mNumDataBytes;

> +      }

> +

> +      EndPointRx (ENDPOINT1, Len);

> +    }

> +  }

> +}

> +

> +//

> +// Instead of actually registering interrupt handlers, we poll the controller's

> +// interrupt source register in this function.

> +//

> +STATIC

> +VOID

> +CheckInterrupts (

> +  IN EFI_EVENT        Event,

> +  IN VOID            *Context

> +  )

> +{

> +  UINT32              Ints;


"Ints" gets a bit confusing in C. Please write it out as interrupts.

> +  UINT32              Data;

> +

> +  //

> +  // interrupt register

> +  //

> +  Ints = READ_REG32 (GINTSTS);

> +

> +  /*

> +   * bus reset

> +   * The core sets this bit to indicate that a reset is detected on the USB.

> +   */

> +  if (Ints & GINTSTS_USBRST) {

> +    WRITE_REG32 (DCFG, DCFG_DESCDMA | DCFG_NZ_STS_OUT_HSHK);

> +    ResetEndpoints ();

> +  }

> +

> +  /*

> +   * enumeration done, we now know the speed

> +   * The core sets this bit to indicate that speed enumeration is complete. The

> +   * application must read the Device Status (DSTS) register to obtain the

> +   * enumerated speed.

> +   */

> +  if (Ints & GINTSTS_ENUMDONE) {

> +    /* Set up the maximum packet sizes accordingly */

> +    UINTN MaxPacket = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : MAX_PACKET_SIZE_CONTROL;


Too long lines. Also an initializer from a ternary.
Please split definition from assignment.

> +    //

> +    // Set Maximum In Packet Size (MPS)

> +    //

> +    Data = READ_REG32 (DIEPCTL1);

> +    Data &= ~DXEPCTL_MPS_MASK;

> +    Data |= MaxPacket;

> +    WRITE_REG32 (DIEPCTL1, Data);

> +    //

> +    //Set Maximum Out Packet Size (MPS)

> +    //

> +    Data = READ_REG32 (DOEPCTL1);

> +    Data &= ~DXEPCTL_MPS_MASK;

> +    Data |= MaxPacket;

> +    WRITE_REG32 (DOEPCTL1, Data);

> +  }

> +

> +  /*

> +   * IN EP event

> +   * The core sets this bit to indicate that an interrupt is pending on one of the IN

> +   * endpoInts of the core (in Device mode). The application must read the

> +   * Device All EndpoInts Interrupt (DAINT) register to determine the exact

> +   * number of the IN endpoint on which the interrupt occurred, and then read

> +   * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to

> +   * determine the exact cause of the interrupt. The application must clear the

> +   * appropriate status bit in the corresponding DIEPINTn register to clear this bit.

> +   */

> +  if (Ints & GINTSTS_IEPINT) {

> +    HandleEndPointInEvent ();

> +  }

> +

> +  /*

> +   * OUT EP event

> +   * The core sets this bit to indicate that an interrupt is pending on one of the

> +   * OUT endpoints of the core (in Device mode). The application must read the

> +   * Device All EndpoInts Interrupt (DAINT) register to determine the exact

> +   * number of the OUT endpoint on which the interrupt occurred, and then read

> +   * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register

> +   * to determine the exact cause of the interrupt. The application must clear the

> +   * appropriate status bit in the corresponding DOEPINTn register to clear this bit.

> +   */


Long lines in comments above, please rewrap.

> +  if (Ints & GINTSTS_OEPINT) {

> +    HandleEndPointOutEvent ();

> +  }

> +

> +  //

> +  // clear ints

> +  //

> +  WRITE_REG32 (GINTSTS, Ints);

> +}

> +

> +EFI_STATUS

> +DwUsbSend (

> +  IN        UINT8  EndpointIndex,

> +  IN        UINTN  Size,

> +  IN  CONST VOID  *Buffer

> +  )

> +{

> +    EndPointTx (EndpointIndex, Buffer, Size);

> +    return EFI_SUCCESS;

> +}

> +

> +STATIC

> +VOID

> +DwUsbInit (

> +  VOID

> +  )

> +{

> +  VOID          *Buf;

> +  UINT32        Data;

> +  EFI_STATUS    Status;

> +

> +  Status = DmaAllocateBuffer (

> +             EfiBootServicesData,

> +             DWUSB_BUFFER_PAGE_NUM,

> +             (VOID *)&Buf

> +             );

> +  if (EFI_ERROR (Status)) {

> +    return;

> +  }

> +  gDmaDesc = Buf;

> +  gDmaDescEp0 = gDmaDesc + sizeof (DwUsbDevDmaDesc);

> +  gDmaDescIn = gDmaDescEp0 + sizeof (DwUsbDevDmaDesc);

> +  gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (DwUsbDevDmaDesc);

> +

> +  ZeroMem (Buf, EFI_PAGE_SIZE * DWUSB_BUFFER_PAGE_NUM);

> +

> +  /* Reset usb controller.*/

> +  /* Wait for OTG AHB master idle */

> +  do {

> +    Data = READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE;

> +  } while (Data == 0);

> +

> +  /* OTG: Assert Software Reset */

> +  WRITE_REG32 (GRSTCTL, GRSTCTL_CSFTRST);

> +

> +  /* Wait for OTG to ack reset */

> +  while ((READ_REG32 (GRSTCTL) & GRSTCTL_CSFTRST) == GRSTCTL_CSFTRST);

> +

> +  /* Wait for OTG AHB master idle */

> +  while ((READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE) == 0);

> +

> +  WRITE_REG32 (GDFIFOCFG, DATA_FIFO_CONFIG);

> +  WRITE_REG32 (GRXFSIZ, RX_SIZE);

> +  WRITE_REG32 (GNPTXFSIZ, ENDPOINT_TX_SIZE);

> +  WRITE_REG32 (DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);

> +  WRITE_REG32 (DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2);

> +  WRITE_REG32 (DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3);

> +  WRITE_REG32 (DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4);

> +  WRITE_REG32 (DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5);

> +  WRITE_REG32 (DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6);

> +  WRITE_REG32 (DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7);

> +  WRITE_REG32 (DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8);

> +  WRITE_REG32 (DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9);

> +  WRITE_REG32 (DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10);

> +  WRITE_REG32 (DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11);

> +  WRITE_REG32 (DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12);

> +  WRITE_REG32 (DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13);

> +  WRITE_REG32 (DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14);

> +  WRITE_REG32 (DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15);

> +

> +  /*

> +   * set Periodic TxFIFO Empty Level,

> +   * Non-Periodic TxFIFO Empty Level,

> +   * Enable DMA, Unmask Global Intr

> +   */

> +  WRITE_REG32 (GAHBCFG, GAHBCFG_CTRL_MASK);

> +

> +  /*select 8bit UTMI+, ULPI Inerface*/

> +  WRITE_REG32 (GUSBCFG, GUSBCFG_USBTRDTIM_8BIT);

> +

> +  /* Detect usb work mode,host or device? */

> +  do {

> +    Data = READ_REG32 (GINTSTS);

> +  } while (Data & GINTSTS_CURMODE_HOST);

> +

> +  /* Init global and device mode csr register. */

> +  /* set Non-Zero-Length status out handshake */

> +  Data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK;


Why 0x20?

/
    Leif

> +  WRITE_REG32 (DCFG, Data);

> +

> +  /* Interrupt unmask: IN event, OUT event, bus reset */

> +  Data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE | GINTSTS_USBRST;

> +  WRITE_REG32 (GINTMSK, Data);

> +

> +  do {

> +    Data = READ_REG32 (GINTSTS) & GINTSTS_ENUMDONE;

> +  } while (Data);

> +

> +  /* Clear any pending OTG Interrupts */

> +  WRITE_REG32 (GOTGINT, ~0);

> +  /* Clear any pending interrupts */

> +  WRITE_REG32 (GINTSTS, ~0);

> +  WRITE_REG32 (GINTMSK, ~0);

> +  Data = READ_REG32 (GOTGINT);

> +  Data &= ~0x3000;   // unknown reserved bits

> +  WRITE_REG32 (GOTGINT, Data);

> +

> +  /* endpoint settings cfg */

> +  ResetEndpoints ();

> +  /* wait for stable */

> +  MicroSecondDelay (1);

> +

> +  /* init finish. and ready to transfer data */

> +

> +  /* Soft Disconnect */

> +  WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE | DCTL_SFTDISCON);

> +  /* wait for stable */

> +  MicroSecondDelay (10000);

> +

> +  /* Soft Reconnect */

> +  WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE);

> +}

> +

> +EFI_STATUS

> +EFIAPI

> +DwUsbStart (

> +  IN USB_DEVICE_DESCRIPTOR   *DeviceDescriptor,

> +  IN VOID                   **Descriptors,

> +  IN USB_DEVICE_RX_CALLBACK   RxCallback,

> +  IN USB_DEVICE_TX_CALLBACK   TxCallback

> +  )

> +{

> +  EFI_STATUS                Status;

> +  EFI_EVENT                 TimerEvent;

> +

> +  if ((DeviceDescriptor == NULL) ||

> +      (Descriptors[0] == NULL) ||

> +      (RxCallback == NULL) ||

> +      (TxCallback == NULL)) {

> +    return EFI_INVALID_PARAMETER;

> +  }

> +

> +  DwUsbInit();

> +

> +  gDwUsbDescriptor.DeviceDescriptor = DeviceDescriptor;

> +  //

> +  // Right now we just support one configuration

> +  //

> +  ASSERT (gDwUsbDescriptor.DeviceDescriptor->NumConfigurations == 1);

> +  gDwUsbDescriptor.DeviceDescriptor->StrManufacturer = DESCRIPTOR_INDEX_MANUFACTURER;

> +  gDwUsbDescriptor.DeviceDescriptor->StrProduct = DESCRIPTOR_INDEX_PRODUCT;

> +  gDwUsbDescriptor.DeviceDescriptor->StrSerialNumber = DESCRIPTOR_INDEX_SERIALNUMBER;

> +  //

> +  // ... and one interface

> +  //

> +  gDwUsbDescriptor.ConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)Descriptors[0];

> +  ASSERT (gDwUsbDescriptor.ConfigDescriptor->NumInterfaces == 1);

> +

> +  mDataReceivedCallback = RxCallback;

> +  mDataSentCallback = TxCallback;

> +

> +  //

> +  // Register a timer event so CheckInterupts gets called periodically

> +  //

> +  Status = gBS->CreateEvent (

> +                  EVT_TIMER | EVT_NOTIFY_SIGNAL,

> +                  TPL_CALLBACK,

> +                  CheckInterrupts,

> +                  NULL,

> +                  &TimerEvent

> +                  );

> +  ASSERT_EFI_ERROR (Status);

> +  if (EFI_ERROR (Status)) {

> +    return Status;

> +  }

> +

> +  Status = gBS->SetTimer (

> +                  TimerEvent,

> +                  TimerPeriodic,

> +                  DW_INTERRUPT_POLL_PERIOD

> +                  );

> +  ASSERT_EFI_ERROR (Status);

> +

> +  return Status;

> +}

> +

> +USB_DEVICE_PROTOCOL mUsbDevice = {

> +  DwUsbStart,

> +  DwUsbSend

> +};

> +

> +

> +EFI_STATUS

> +EFIAPI

> +DwUsbEntryPoint (

> +  IN EFI_HANDLE                            ImageHandle,

> +  IN EFI_SYSTEM_TABLE                      *SystemTable

> +  )

> +{

> +  EFI_STATUS      Status;

> +

> +  Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb);

> +  if (EFI_ERROR (Status)) {

> +    return Status;

> +  }

> +

> +  Status = DwUsb->PhyInit(USB_DEVICE_MODE);

> +  if (EFI_ERROR (Status)) {

> +    return Status;

> +  }

> +

> +  return gBS->InstallProtocolInterface (

> +                &ImageHandle,

> +                &gUsbDeviceProtocolGuid,

> +                EFI_NATIVE_INTERFACE,

> +                &mUsbDevice

> +                );

> +}

> -- 

> 2.7.4

> 

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

> On Tue, Aug 21, 2018 at 07:35:13PM +0800, Haojian Zhuang wrote:

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

> >

> > Cc: Leif Lindholm <leif.lindholm@linaro.org>

> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> > Contributed-under: TianoCore Contribution Agreement 1.1

> > Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>

> > ---

> >  EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec |  45 +

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

> >  EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.h   | 655 ++++++++++++++

> >  EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.c   | 912 ++++++++++++++++++++

> >  4 files changed, 1664 insertions(+)

>

> Could it be renamed DwUsb2? This seems to match how Synopsys

> themselves refer to it, and what the Linux driver is called.

>

OK

> Other than that, same comments as for DwUsb3Dxe - please move it to

> edk2-platforms and convert it to UEFI driver model with

> NonDiscoverableDeviceRegistrationLib.

UsbDevice isn't supported by NonDiscoverableDeviceRegistrationLib.
Could I add a new type?

>

> Hmm, it also looks to me like there are plenty of things here

> hardcoded for the use as a device for fastboot. I don't object to

> that being the only support submitted, you made it clear when you

> posted it. But the code is completely geared towards this, and I feel

> if someone comes along and want to add the functionality to run it in

> host mode.


I hope to support device first.
>

> I expect I will find the same when I look at the reworked version of DwUsb3Dxe.

>

> Is there anything you can do to break out the generic device

> configuration bits from the bits that assume there are two endpoints

> and they are being used for fastboot?


Let me investigate.

>

> >

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

> > new file mode 100644

> > index 000000000000..7eb65e498c04

> > --- /dev/null

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

> > @@ -0,0 +1,45 @@

> > +#/** @file

> > +# Framework Module Development Environment Industry Standards

> > +#

> > +# This Package provides headers and libraries that conform to EFI/PI Industry standards.

> > +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>

> > +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR>

> > +# Copyright (c) 2018, Linaro. All rights reserved.<BR>

>

> Same comments as for DwUsb3 - please merge these two into a common one

> for both drivers (if still needed).

>

> > +#

> > +#    This program and the accompanying materials are licensed and made available under

> > +#    the terms and conditions of the BSD License which accompanies this distribution.

> > +#    The full text of the license may be found at

> > +#    http://opensource.org/licenses/bsd-license.php

> > +#

> > +#    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> > +#    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> > +#

> > +#**/

> > +

> > +[Defines]

> > +  DEC_SPECIFICATION              = 0x00010019

> > +  PACKAGE_NAME                   = DwUsbDxePkg

> > +  PACKAGE_GUID                   = 114a3be9-10f7-4bf1-81ca-09ac52d4c3d5

> > +  PACKAGE_VERSION                = 0.1

> > +

> > +

> > +################################################################################

> > +#

> > +# Include Section - list of Include Paths that are provided by this package.

> > +#                   Comments are used for Keywords and Module Types.

> > +#

> > +# Supported Module Types:

> > +#  BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION

> > +#

> > +################################################################################

> > +

> > +[Guids.common]

> > +  gDwUsbDxeTokenSpaceGuid       = { 0x131c4d02, 0x9449, 0x4ee9, { 0xba, 0x3d, 0x69, 0x50, 0x21, 0x89, 0x26, 0x0b }}

> > +

> > +[Protocols.common]

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

> > +

> > +[PcdsFixedAtBuild.common]

> > +  # DwUsb Driver PCDs

> > +  gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0x0|UINT32|0x00000001

> > +  gDwUsbDxeTokenSpaceGuid.PcdSysCtrlBaseAddress|0x0|UINT32|0x00000002

>

> I don't see PcdSysCtrlBaseAddress used anywhere in this patch? It also

> doesn't sound like something that should be an aspect of the USB

> controller driver.

>

Yes, PcdSysCtrlBaseAddress isn't used. We could remove it now.

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

> > new file mode 100644

> > index 000000000000..56d518c27c32

> > --- /dev/null

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

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

> > +#/** @file

> > +#

> > +#  Copyright (c) 2018, Linaro. All rights reserved.

> > +#

> > +#  This program and the accompanying materials are licensed and made available

> > +#  under the terms and conditions of the BSD License which accompanies this

> > +#  distribution. The full text of the license may be found at

> > +#  http://opensource.org/licenses/bsd-license.php

> > +#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> > +#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> > +#

> > +#

> > +#**/

> > +

> > +[Defines]

> > +  INF_VERSION                    = 0x00010019

> > +  BASE_NAME                      = DwUsbDxe

> > +  FILE_GUID                      = 72d78ea6-4dee-11e3-8100-f3842a48d0a0

> > +  MODULE_TYPE                    = UEFI_DRIVER

> > +  VERSION_STRING                 = 1.0

> > +  ENTRY_POINT                    = DwUsbEntryPoint

> > +

> > +[Sources.common]

> > +  DwUsbDxe.c

> > +

> > +[LibraryClasses]

> > +  ArmLib

>

> This is not an ARM-specific device, so it should not need ArmLib to build.

>

Because I used ArmDataSynchronizationBarrier(). Do we have the common
function on it?

> > +  CacheMaintenanceLib

> > +  DebugLib

> > +  DmaLib

> > +  IoLib

> > +  MemoryAllocationLib

> > +  TimerLib

> > +  UefiBootServicesTableLib

> > +  UefiDriverEntryPoint

> > +

> > +[Protocols]

> > +  gEfiDriverBindingProtocolGuid

> > +  gUsbDeviceProtocolGuid

> > +

> > +[Packages]

> > +  ArmPkg/ArmPkg.dec

>

> Hmm?

>

> > +  EmbeddedPkg/Drivers/DwUsbDxe/DwUsbDxe.dec

> > +  EmbeddedPkg/EmbeddedPkg.dec

> > +  MdeModulePkg/MdeModulePkg.dec

> > +  MdePkg/MdePkg.dec

> > +

> > +[Pcd]

> > +  gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress

> > +

> > +[Depex]

> > +  TRUE

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

> > new file mode 100644

> > index 000000000000..1595e09a92a4

> > --- /dev/null

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

> > @@ -0,0 +1,655 @@

> > +/** @file

> > +

> > +  Copyright (c) 2018, Linaro. All rights reserved.

> > +

> > +  This program and the accompanying materials are licensed and made available

> > +  under the terms and conditions of the BSD License which accompanies this

> > +  distribution.  The full text of the license may be found at

> > +  http://opensource.org/licenses/bsd-license.php

> > +

> > +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> > +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> > +

> > +**/

> > +

> > +#ifndef __DW_USB_DXE_H__

> > +#define __DW_USB_DXE_H__

>

> Preferably expand all DW_ to DESIGNWARE_.

OK

>

> > +

> > +#define DW_USB_BASE                     FixedPcdGet32 (PcdDwUsbDxeBaseAddress)

> > +

> > +#define HPTXFSIZ                        0x100

> > +#define DIEPTXF(x)                      (0x100 + 4 * (x))

>

> Why 4 *?

> Is this a sizeof (UINT32)?


Yes, it's a sizeof (UINT32).

>

> > +#define DIEPTXF1                        0x104

> > +#define DIEPTXF2                        0x108

> > +#define DIEPTXF3                        0x10C

> > +#define DIEPTXF4                        0x110

> > +#define DIEPTXF5                        0x114

> > +#define DIEPTXF6                        0x118

> > +#define DIEPTXF7                        0x11C

> > +#define DIEPTXF8                        0x120

> > +#define DIEPTXF9                        0x124

> > +#define DIEPTXF10                       0x128

> > +#define DIEPTXF11                       0x12C

> > +#define DIEPTXF12                       0x130

> > +#define DIEPTXF13                       0x134

> > +#define DIEPTXF14                       0x138

> > +#define DIEPTXF15                       0x13C

> > +

> > +/*** HOST MODE REGISTERS ***/

> > +/* Host Global Registers */

> > +#define HCFG                            0x400

> > +#define HFIR                            0x404

> > +#define HFNUM                           0x408

> > +#define HPTXSTS                         0x410

> > +#define HAINT                           0x414

> > +#define HAINTMSK                        0x418

> > +

> > +/* Host Port Control and Status Registers */

> > +#define HPRT                            0x440

> > +

> > +/* Host Channel-Specific Registers */

> > +#define HCCHAR(x)                       (0x500 + 0x20 * (x))

> > +#define HCSPLT(x)                       (0x504 + 0x20 * (x))

> > +#define HCINT(x)                        (0x508 + 0x20 * (x))

> > +#define HCINTMSK(x)                     (0x50C + 0x20 * (x))

> > +#define HCTSIZ(x)                       (0x510 + 0x20 * (x))

> > +#define HCDMA(x)                        (0x514 + 0x20 * (x))

>

> Why 0x20 *?

> CHANNEL_REGISTER_BANK_SIZE?


Yes. I'll add a new definition of CHANNEL_REGISTER_BANK_SIZE.

>

> > +#define HCCHAR15                        0x6E0

> > +#define HCSPLT15                        0x6E4

> > +#define HCINT15                         0x6E8

> > +#define HCINTMSK15                      0x6EC

> > +#define HCTSIZ15                        0x6F0

> > +#define HCDMA15                         0x6F4

>

> Why does this hold both the macros to calculate the offsets for a

> given channel and all of the absolute register offsets per channel?

>


OK. I'll only use one method.

> > +

> > +/*** DEVICE MODE REGISTERS ***/

> > +/* Device Global Registers */

> > +#define DCFG                            0x800

> > +#define DCFG_DESCDMA                    BIT23

> > +#define DCFG_EPMISCNT_MASK              (0x1F << 18)

> > +#define DCFG_EPMISCNT_SHIFT             18

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

> > +#define DCFG_DEVADDR_SHIFT              4

> > +#define DCFG_DEVADDR(x)                 (((x) << DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK)

> > +#define DCFG_NZ_STS_OUT_HSHK            BIT2

> > +

> > +#define DCTL                            0x804

> > +#define DCTL_PWRONPRGDONE               BIT11

> > +#define DCTL_GNPINNAKSTS                BIT2

> > +#define DCTL_SFTDISCON                  BIT1

> > +

> > +#define DSTS                            0x808

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

> > +#define DSTS_ENUMSPD_HIGH               (0 << 1)

> > +#define DSTS_ENUMSPD_FULL               (1 << 1)

> > +

> > +#define DIEPMSK                         0x810

> > +#define DOEPMSK                         0x814

> > +

> > +#define DXEPMSK_TIMEOUTMSK              BIT3

> > +#define DXEPMSK_AHBERMSK                BIT2

> > +#define DXEPMSK_XFERCOMPLMSK            BIT0

> > +

> > +#define DAINT                           0x818

> > +#define DAINTMSK                        0x81C

> > +

> > +#define DAINTMSK_OUTEPMSK_SHIFT         16

> > +#define DAINTMSK_INEPMSK_SHIFT          0

> > +

> > +#define DTKNQR1                         0x820

> > +#define DTKNQR2                         0x824

> > +#define DVBUSDIS                        0x828

> > +#define DVBUSPULSE                      0x82C

> > +#define DTHRCTL                         0x830

> > +

> > +/* Device Logical IN Endpoint-Specific Registers */

> > +#define DIEPCTL(x)                      (0x900 + 0x20 * (x))

> > +#define DIEPINT(x)                      (0x908 + 0x20 * (x))

> > +#define DIEPTSIZ(x)                     (0x910 + 0x20 * (x))

> > +#define DIEPDMA(x)                      (0x914 + 0x20 * (x))

> > +#define DTXFSTS(x)                      (0x918 + 0x20 * (x))

>

> Same again - please add a #define for that 0x20.

OK.

>

> > +

> > +#define DIEPCTL0                        0x900

> > +#define DIEPINT0                        0x908

> > +#define DIEPTSIZ0                       0x910

> > +#define DIEPDMA0                        0x914

> > +#define DIEPCTL1                        0x920

> > +#define DIEPINT1                        0x928

> > +#define DIEPTSIZ1                       0x930

> > +#define DIEPDMA1                        0x934

> > +#define DIEPCTL2                        0x940

> > +#define DIEPINT2                        0x948

> > +#define DIEPTSIZ2                       0x950

> > +#define DIEPDMA2                        0x954

> > +#define DIEPCTL3                        0x960

> > +#define DIEPINT3                        0x968

> > +#define DIEPTSIZ3                       0x970

> > +#define DIEPDMA3                        0x974

> > +#define DIEPCTL4                        0x980

> > +#define DIEPINT4                        0x988

> > +#define DIEPTSIZ4                       0x990

> > +#define DIEPDMA4                        0x994

> > +#define DIEPCTL5                        0x9A0

> > +#define DIEPINT5                        0x9A8

> > +#define DIEPTSIZ5                       0x9B0

> > +#define DIEPDMA5                        0x9B4

> > +#define DIEPCTL6                        0x9C0

> > +#define DIEPINT6                        0x9C8

> > +#define DIEPTSIZ6                       0x9D0

> > +#define DIEPDMA6                        0x9D4

> > +#define DIEPCTL7                        0x9E0

> > +#define DIEPINT7                        0x9E8

> > +#define DIEPTSIZ7                       0x9F0

> > +#define DIEPDMA7                        0x9F4

> > +#define DIEPCTL8                        0xA00

> > +#define DIEPINT8                        0xA08

> > +#define DIEPTSIZ8                       0xA10

> > +#define DIEPDMA8                        0xA14

> > +#define DIEPCTL9                        0xA20

> > +#define DIEPINT9                        0xA28

> > +#define DIEPTSIZ9                       0xA30

> > +#define DIEPDMA9                        0xA34

> > +#define DIEPCTL10                       0xA40

> > +#define DIEPINT10                       0xA48

> > +#define DIEPTSIZ10                      0xA50

> > +#define DIEPDMA10                       0xA54

> > +#define DIEPCTL11                       0xA60

> > +#define DIEPINT11                       0xA68

> > +#define DIEPTSIZ11                      0xA70

> > +#define DIEPDMA11                       0xA74

> > +#define DIEPCTL12                       0xA80

> > +#define DIEPINT12                       0xA88

> > +#define DIEPTSIZ12                      0xA90

> > +#define DIEPDMA12                       0xA94

> > +#define DIEPCTL13                       0xAA0

> > +#define DIEPINT13                       0xAA8

> > +#define DIEPTSIZ13                      0xAB0

> > +#define DIEPDMA13                       0xAB4

> > +#define DIEPCTL14                       0xAC0

> > +#define DIEPINT14                       0xAC8

> > +#define DIEPTSIZ14                      0xAD0

> > +#define DIEPDMA14                       0xAD4

> > +#define DIEPCTL15                       0xAE0

> > +#define DIEPINT15                       0xAE8

> > +#define DIEPTSIZ15                      0xAF0

> > +#define DIEPDMA15                       0xAF4

>

> And again, why do we have both macros and all of the possible combinations?


OK. I'll pick one method only.

>

> > +

> > +/* Device Logical OUT Endpoint-Specific Registers */

> > +#define DOEPCTL(x)                      (0xB00 + 0x20 * (x))

> > +#define DOEPINT(x)                      (0xB08 + 0x20 * (x))

> > +#define DOEPTSIZ(x)                     (0xB10 + 0x20 * (x))

> > +

> > +#define DXEPINT_EPDISBLD                BIT1

> > +#define DXEPINT_XFERCOMPL               BIT0

> > +

> > +#define DXEPTSIZ_SUPCNT(x)              (((x) & 0x3) << 29)

> > +#define DXEPTSIZ_PKTCNT(x)              (((x) & 0x3) << 19)

> > +#define DXEPTSIZ_XFERSIZE(x)            ((x) & 0x7F)

> > +

> > +#define DOEPDMA(x)                      (0xB14 + 0x20 * (x))

>

> Move this up to below DOEPTSIZ?

> Delete all of the below definitions and use the macros instead

> And a #define for that 0x20?

>

OK

> > +#define DOEPCTL0                        0xB00

> > +#define DOEPINT0                        0xB08

> > +#define DOEPTSIZ0                       0xB10

> > +#define DOEPDMA0                        0xB14

> > +#define DOEPCTL1                        0xB20

> > +#define DOEPINT1                        0xB28

> > +#define DOEPTSIZ1                       0xB30

> > +#define DOEPDMA1                        0xB34

> > +#define DOEPCTL2                        0xB40

> > +#define DOEPINT2                        0xB48

> > +#define DOEPTSIZ2                       0xB50

> > +#define DOEPDMA2                        0xB54

> > +#define DOEPCTL3                        0xB60

> > +#define DOEPINT3                        0xB68

> > +#define DOEPTSIZ3                       0xB70

> > +#define DOEPDMA3                        0xB74

> > +#define DOEPCTL4                        0xB80

> > +#define DOEPINT4                        0xB88

> > +#define DOEPTSIZ4                       0xB90

> > +#define DOEPDMA4                        0xB94

> > +#define DOEPCTL5                        0xBA0

> > +#define DOEPINT5                        0xBA8

> > +#define DOEPTSIZ5                       0xBB0

> > +#define DOEPDMA5                        0xBB4

> > +#define DOEPCTL6                        0xBC0

> > +#define DOEPINT6                        0xBC8

> > +#define DOEPTSIZ6                       0xBD0

> > +#define DOEPDMA6                        0xBD4

> > +#define DOEPCTL7                        0xBE0

> > +#define DOEPINT7                        0xBE8

> > +#define DOEPTSIZ7                       0xBF0

> > +#define DOEPDMA7                        0xBF4

> > +#define DOEPCTL8                        0xC00

> > +#define DOEPINT8                        0xC08

> > +#define DOEPTSIZ8                       0xC10

> > +#define DOEPDMA8                        0xC14

> > +#define DOEPCTL9                        0xC20

> > +#define DOEPINT9                        0xC28

> > +#define DOEPTSIZ9                       0xC30

> > +#define DOEPDMA9                        0xC34

> > +#define DOEPCTL10                       0xC40

> > +#define DOEPINT10                       0xC48

> > +#define DOEPTSIZ10                      0xC50

> > +#define DOEPDMA10                       0xC54

> > +#define DOEPCTL11                       0xC60

> > +#define DOEPINT11                       0xC68

> > +#define DOEPTSIZ11                      0xC70

> > +#define DOEPDMA11                       0xC74

> > +#define DOEPCTL12                       0xC80

> > +#define DOEPINT12                       0xC88

> > +#define DOEPTSIZ12                      0xC90

> > +#define DOEPDMA12                       0xC94

> > +#define DOEPCTL13                       0xCA0

> > +#define DOEPINT13                       0xCA8

> > +#define DOEPTSIZ13                      0xCB0

> > +#define DOEPDMA13                       0xCB4

> > +#define DOEPCTL14                       0xCC0

> > +#define DOEPINT14                       0xCC8

> > +#define DOEPTSIZ14                      0xCD0

> > +#define DOEPDMA14                       0xCD4

> > +#define DOEPCTL15                       0xCE0

> > +#define DOEPINT15                       0xCE8

> > +#define DOEPTSIZ15                      0xCF0

> > +#define DOEPDMA15                       0xCF4

> > +

> > +#define DXEPCTL_EPENA                   BIT31

> > +#define DXEPCTL_SNAK                    BIT27

> > +#define DXEPCTL_CNAK                    BIT26

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

> > +#define DXEPCTL_STALL                   BIT21

> > +#define DXEPCTL_EPTYPE_MASK             (BIT19 | BIT18)

> > +#define DXEPCTL_EPTYPE(x)               (((x) & 0x3) << 18)

> > +#define DXEPCTL_NAKSTS                  BIT17

> > +#define DXEPCTL_USBACTEP                BIT15

> > +#define DXEPCTL_MPS_MASK                0x7FF

> > +

> > +#define DXEPTSIZN_PKTCNT_MASK           (0x3FF << 19)

> > +#define DXEPTSIZN_PKTCNT(x)             (((x) & 0x3FF) << 19)

> > +#define DXEPTSIZN_XFERSIZE_MASK         0x7FFFF

> > +#define DXEPTSIZN_XFERSIZE(x)           ((x) & 0x7FFFF)

> > +

> > +/* Power and Clock Gating Register */

> > +#define PCGCCTL                         0xE00

> > +

> > +#define EP0FIFO                         0x1000

> > +

> > +/**

> > + * This union represents the bit fields in the DMA Descriptor

> > + * status quadlet. Read the quadlet into the <i>d32</i> member then

> > + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and

> > + * <i>b_iso_in</i> elements.

> > + */

>

> Drop the HTML formatting please.

>

OK

> > +typedef union {

> > +  /** raw register data */

> > +  UINT32 d32;

> > +    /** quadlet bits */

> > +  struct {

> > +    /** Received number of bytes */

> > +    unsigned bytes:16;

> > +    /** NAK bit - only for OUT EPs */

> > +    unsigned nak:1;

> > +    unsigned reserved17_22:6;

> > +    /** Multiple Transfer - only for OUT EPs */

> > +    unsigned mtrf:1;

> > +    /** Setup Packet received - only for OUT EPs */

> > +    unsigned sr:1;

> > +    /** Interrupt On Complete */

> > +    unsigned ioc:1;

> > +    /** Short Packet */

> > +    unsigned sp:1;

> > +    /** Last */

> > +    unsigned l:1;

> > +    /** Receive Status */

> > +    unsigned sts:2;

> > +    /** Buffer Status */

> > +    unsigned bs:2;

> > +  } b;

> > +} DevDmaDescStatus;

>

> This struct does not conform to coding style.

>

OK. I'll use macro definition instead.

> > +

> > +/**

> > + * DMA Descriptor structure

> > + *

> > + * DMA Descriptor structure contains two quadlets:

> > + * Status quadlet and Data buffer pointer.

> > + */

> > +typedef struct {

> > +  /** DMA Descriptor status quadlet */

> > +  DevDmaDescStatus status;

> > +  /** DMA Descriptor data buffer pointer */

> > +  UINT32 buf;

> > +} DwUsbDevDmaDesc;

> > +

> > +#endif /* __DW_USB_DXE_H__ */

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

> > new file mode 100644

> > index 000000000000..6e1086190796

> > --- /dev/null

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

> > @@ -0,0 +1,912 @@

> > +/** @file

> > +

> > +  Copyright (c) 2018, Linaro. All rights reserved.

> > +

> > +  This program and the accompanying materials are licensed and made available

> > +  under the terms and conditions of the BSD License which accompanies this

> > +  distribution.  The full text of the license may be found at

> > +  http://opensource.org/licenses/bsd-license.php

> > +

> > +  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

> > +  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

> > +

> > +**/

> > +

> > +#include <IndustryStandard/Usb.h>

> > +#include <Library/ArmLib.h>

>

> Hmm?

>

> > +#include <Library/BaseLib.h>

> > +#include <Library/BaseMemoryLib.h>

> > +#include <Library/CacheMaintenanceLib.h>

> > +#include <Library/DebugLib.h>

> > +#include <Library/DmaLib.h>

> > +#include <Library/IoLib.h>

> > +#include <Library/MemoryAllocationLib.h>

> > +#include <Library/TimerLib.h>

> > +#include <Library/UefiBootServicesTableLib.h>

> > +#include <Library/UefiDriverEntryPoint.h>

> > +#include <Library/UefiRuntimeServicesTableLib.h>

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

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

> > +

> > +#include "DwUsbDxe.h"

> > +

> > +#define USB_TYPE_LENGTH               16

>

> What type?

I'll add comment on it.

>

> > +#define USB_BLOCK_HIGH_SPEED_SIZE     512

>

> What size?

>

> > +#define DATA_SIZE                     32768

>

> What data?

>

> > +#define CMD_SIZE                      512

>

> What command?

>

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

>

> This macro is used exactly once. Please just inline the call (with ==

> 0 instead of !).

>

OK

> > +

> > +//

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

> > +// 10 Microseconds

> > +//

> > +#define DW_INTERRUPT_POLL_PERIOD      10000

> > +

> > +#define ENDPOINT0                     0

> > +#define ENDPOINT1                     1

> > +

> > +#define DIR_OUT                       0

> > +#define DIR_IN                        1

> > +

> > +#define DWUSB_BUFFER_PAGE_NUM         16

> > +

> > +#define DESCRIPTOR_INDEX_LANG         0

> > +#define DESCRIPTOR_INDEX_MANUFACTURER 1

> > +#define DESCRIPTOR_INDEX_PRODUCT      2

> > +#define DESCRIPTOR_INDEX_SERIALNUMBER 3

> > +

> > +#define DESCRIPTOR_TYPE(x)            (((x) >> 8) & 0xFF)

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

> > +

> > +typedef struct {

> > +  USB_DEVICE_DESCRIPTOR        *DeviceDescriptor;

> > +  USB_CONFIG_DESCRIPTOR        *ConfigDescriptor;

> > +} DW_USB_DESCRIPTOR;

>

> Please move everything after my last comment to here into DwUsbDxe.h.

> Or DwUsb2Dxe.h, I guess it should be called.

>


OK

> > +

> > +EFI_GUID  gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;

>

> Problematic, as mentioned in comment on DwUsb3Dxe.

>

> > +

> > +STATIC DwUsbDevDmaDesc  *gDmaDesc,*gDmaDescEp0,*gDmaDescIn;

> > +STATIC USB_DEVICE_REQUEST      *gCtrlReq;

> > +STATIC VOID                    *RxBuf;

> > +STATIC UINTN                   RxDescBytes;

> > +STATIC UINTN                   mNumDataBytes;

> > +

> > +STATIC DW_USB_PROTOCOL         *DwUsb;

> > +STATIC DW_USB_DESCRIPTOR       gDwUsbDescriptor;

>

> Please use 'm' prefix on all STATIC globals.

>


OK

> > +

> > +STATIC USB_DEVICE_RX_CALLBACK  mDataReceivedCallback;

> > +STATIC USB_DEVICE_TX_CALLBACK  mDataSentCallback;

> > +

> > +

> > +/* To detect which mode was run, high speed or full speed */

> > +STATIC

> > +UINTN

> > +UsbDrvPortSpeed (

> > +  VOID

> > +  )

> > +{

> > +  return (((READ_REG32 (DSTS) & DSTS_ENUMSPD_MASK) == DSTS_ENUMSPD_HIGH));

> > +}

> > +

> > +STATIC

> > +VOID

> > +ResetEndpoints (

> > +  VOID

> > +  )

> > +{

> > +  UINT32                       Data;

> > +

> > +  /* EP0 IN ACTIVE NEXT=1 */

> > +  WRITE_REG32 (DIEPCTL0, DXEPCTL_USBACTEP | BIT11);

> > +

> > +  /* EP0 OUT ACTIVE */

> > +  WRITE_REG32 (DOEPCTL0, DXEPCTL_USBACTEP);

> > +

> > +  /* Clear any pending OTG Interrupts */

> > +  WRITE_REG32 (GOTGINT, ~0);

> > +

> > +  /* Clear any pending interrupts */

> > +  WRITE_REG32 (GINTSTS, ~0);

> > +  WRITE_REG32 (DIEPINT0, ~0);

> > +  WRITE_REG32 (DOEPINT0, ~0);

> > +  WRITE_REG32 (DIEPINT1, ~0);

> > +  WRITE_REG32 (DOEPINT1, ~0);

> > +

> > +  /* IN EP interrupt mask */

> > +  WRITE_REG32 (DIEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);

> > +  /* OUT EP interrupt mask */

> > +  WRITE_REG32 (DOEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);

> > +  /* Enable interrupts on EndPoint0 */

> > +  WRITE_REG32 (DAINTMSK, (1 << DAINTMSK_OUTEPMSK_SHIFT) | (1 << DAINTMSK_INEPMSK_SHIFT));

> > +

> > +  /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/

> > +  WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));

>

> Long lines above.

>

OK

> > +

> > +  //

> > +  //notes that:the compulsive conversion is expectable.

>

> What does this mean?

>

> > +  //

> > +  gDmaDescEp0->status.b.bs = 0x3;

> > +  gDmaDescEp0->status.b.mtrf = 0;

> > +  gDmaDescEp0->status.b.sr = 0;

> > +  gDmaDescEp0->status.b.l = 1;

> > +  gDmaDescEp0->status.b.ioc = 1;

> > +  gDmaDescEp0->status.b.sp = 0;

> > +  gDmaDescEp0->status.b.bytes = 64;

> > +  gDmaDescEp0->buf = (UINT32)(UINTN)gCtrlReq;

> > +  gDmaDescEp0->status.b.sts = 0;

> > +  gDmaDescEp0->status.b.bs = 0x0;

>

> What do all of these live-coded values mean?

> Need #defines or possibly comments.

>

OK

> > +  WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)gDmaDescEp0);

> > +  /* EP0 OUT ENABLE CLEARNAK */

> > +  Data = READ_REG32 (DOEPCTL0);

> > +  WRITE_REG32 (DOEPCTL0, Data | DXEPCTL_EPENA | DXEPCTL_CNAK);

> > +}

> > +

> > +STATIC

> > +VOID

> > +EndPointTx (

> > +  IN UINT8          EndPoint,

> > +  IN CONST VOID    *Ptr,

> > +  IN UINTN          Len

> > +  )

> > +{

> > +  UINT32            BlockSize;

> > +  UINT32            Packets;

> > +  UINT32            Data;

> > +

> > +  /* EPx OUT ACTIVE */

> > +  Data = READ_REG32 (DIEPCTL (EndPoint));

> > +  WRITE_REG32 (DIEPCTL (EndPoint), Data | DXEPCTL_USBACTEP);

> > +  if (!EndPoint) {

> > +      BlockSize = 64;

> > +  } else {

> > +      BlockSize = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;

>

> I will want #defines for those 64.

> Among other things that will tell me if it's the same 64 or whether

> they happen to have the same numeric value.

>

OK

> > +  }

> > +  Packets = (Len + BlockSize - 1) / BlockSize;

> > +

> > +  if (!Len) {

> > +    /* send one empty packet */

> > +    gDmaDescIn->status.b.bs = 0x3;

> > +    gDmaDescIn->status.b.l = 1;

> > +    gDmaDescIn->status.b.ioc = 1;

> > +    gDmaDescIn->status.b.sp = 1;

> > +    gDmaDescIn->status.b.bytes = 0;

> > +    gDmaDescIn->buf = 0;

> > +    gDmaDescIn->status.b.sts = 0;

> > +    gDmaDescIn->status.b.bs = 0x0;

>

> #defines and/or comments for numbers.

>

OK

> > +

> > +    WRITE_REG32 (DIEPDMA (EndPoint), (UINT32)(UINTN)gDmaDescIn);             // DMA Address (DMAAddr) is zero

> > +  } else {

> > +    WRITE_REG32 (DIEPTSIZ (EndPoint), Len | DXEPTSIZN_PKTCNT (Packets));

> > +

> > +    //

> > +    //flush cache

> > +    //

> > +    WriteBackDataCacheRange ((VOID *)Ptr, Len);

> > +

> > +    gDmaDescIn->status.b.bs = 0x3;

> > +    gDmaDescIn->status.b.l = 1;

> > +    gDmaDescIn->status.b.ioc = 1;

> > +    gDmaDescIn->status.b.sp = 1;

> > +    gDmaDescIn->status.b.bytes = Len;

> > +    gDmaDescIn->buf = (UINT32)(UINTN)Ptr;

> > +    gDmaDescIn->status.b.sts = 0;

> > +    gDmaDescIn->status.b.bs = 0x0;

>

> #defines and/or comments for numbers.

>

OK

> > +    WRITE_REG32 (DIEPDMA (EndPoint), (UINT32)(UINTN)gDmaDescIn);         // Ptr is DMA address

> > +  }

> > +  ArmDataSynchronizationBarrier ();

>

> MemoryFence ()?

>

Thanks. I'll check it.

> > +  /* epena & cnak */

> > +  Data = READ_REG32 (DIEPCTL (EndPoint));

> > +  WRITE_REG32 (DIEPCTL (EndPoint), Data | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11);

> > +}

> > +

> > +STATIC

> > +VOID

> > +EndPointRx (

> > +  IN UINTN            EndPoint,

> > +  IN UINTN            Len

> > +  )

> > +{

> > +  UINT32              Data;

> > +

> > +  /* EPx UNSTALL */

> > +  Data = READ_REG32 (DOEPCTL (EndPoint));

> > +  WRITE_REG32 (DOEPCTL (EndPoint), Data & ~DXEPCTL_STALL);

> > +  /* EPx OUT ACTIVE */

> > +  Data = READ_REG32 (DOEPCTL (EndPoint));

> > +  WRITE_REG32 (DOEPCTL (EndPoint), Data | DXEPCTL_USBACTEP);

> > +

> > +  if (Len >= DATA_SIZE) {

> > +    RxDescBytes = DATA_SIZE;

> > +  } else {

> > +    RxDescBytes = Len;

> > +  }

> > +

> > +  RxBuf = AllocatePool (DATA_SIZE);

> > +  if (RxBuf == NULL) {

> > +    DEBUG ((DEBUG_ERROR, "EndPointRx: failed to allocate buffer\n"));

> > +    return;

> > +  }

> > +

> > +  InvalidateDataCacheRange (RxBuf, Len);

> > +

> > +  gDmaDesc->status.b.bs = 0x3;

> > +  gDmaDesc->status.b.mtrf = 0;

> > +  gDmaDesc->status.b.sr = 0;

> > +  gDmaDesc->status.b.l = 1;

> > +  gDmaDesc->status.b.ioc = 1;

> > +  gDmaDesc->status.b.sp = 0;

> > +  gDmaDesc->status.b.bytes = (UINT32)RxDescBytes;

> > +  gDmaDesc->buf = (UINT32)(UINTN)RxBuf;

> > +  gDmaDesc->status.b.sts = 0;

> > +  gDmaDesc->status.b.bs = 0x0;

>

> #defines and/or comments for numbers.

>

OK

> > +

> > +  ArmDataSynchronizationBarrier ();

>

> MemoryFence ()?

>

OK

> > +  WRITE_REG32 (DOEPDMA (EndPoint), (UINT32)(UINTN)gDmaDesc);

> > +  /* EPx OUT ENABLE CLEARNAK */

> > +  Data = READ_REG32 (DOEPCTL (EndPoint));

> > +  WRITE_REG32 (DOEPCTL (EndPoint), Data | DXEPCTL_EPENA | DXEPCTL_CNAK);

> > +}

> > +

> > +STATIC

> > +EFI_STATUS

> > +HandleGetDescriptor (

> > +  IN USB_DEVICE_REQUEST  *Request

> > +  )

> > +{

> > +  UINTN                             ResponseSize;

> > +  VOID                             *ResponseData;

> > +  EFI_USB_STRING_DESCRIPTOR        *Descriptor = NULL;

> > +  UINTN                             DescriptorSize;

> > +

> > +  ResponseSize = 0;

> > +  ResponseData = NULL;

> > +

> > +  // Pretty confused if bmRequestType is anything but this:

> > +  if (Request->RequestType != USB_DEV_GET_DESCRIPTOR_REQ_TYPE) {

> > +    return EFI_INVALID_PARAMETER;

> > +  }

> > +

> > +  //

> > +  // Choose the response

> > +  //

> > +  switch (DESCRIPTOR_TYPE(Request->Value)) {

> > +  case USB_DESC_TYPE_DEVICE:

> > +    DEBUG ((DEBUG_INFO, "DwUsbDxe: Got a request for device descriptor\n"));

> > +    ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);

> > +    ResponseData = gDwUsbDescriptor.DeviceDescriptor;

> > +    break;

> > +  case USB_DESC_TYPE_CONFIG:

> > +    DEBUG ((DEBUG_INFO, "DwUsbDxe: Got a request for config descriptor\n"));

> > +    ResponseSize = gDwUsbDescriptor.ConfigDescriptor->TotalLength;

> > +    ResponseData = gDwUsbDescriptor.ConfigDescriptor;

> > +    break;

> > +  case USB_DESC_TYPE_STRING:

> > +    DEBUG ((

> > +      DEBUG_INFO,

> > +      "DwUsbDxe: Got a request for String descriptor %d\n",

> > +      Request->Value & 0xFF

> > +      ));

> > +    switch (DESCRIPTOR_INDEX(Request->Value)) {

>

> Put the nested switch in a separate function, this is unreadable.

>

OK

> > +    case 0:

> > +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +

> > +                       (LANG_LENGTH + 1) * sizeof (CHAR16);

> > +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);

> > +      if (Descriptor == NULL) {

> > +        return EFI_OUT_OF_RESOURCES;

> > +      }

> > +      Descriptor->Length = LANG_LENGTH * sizeof (CHAR16);

> > +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;

> > +      DwUsb->GetLang (Descriptor->String, &Descriptor->Length);

> > +      ResponseSize = Descriptor->Length;

> > +      ResponseData = Descriptor;

> > +      break;

> > +    case 1:

> > +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +

> > +                       (MANU_FACTURER_STRING_LENGTH + 1) * sizeof (CHAR16);

> > +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);

> > +      if (Descriptor == NULL) {

> > +        return EFI_OUT_OF_RESOURCES;

> > +      }

> > +      Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);

> > +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;

> > +      DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length);

> > +      ResponseSize = Descriptor->Length;

> > +      ResponseData = Descriptor;

> > +      break;

> > +    case 2:

> > +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +

> > +                       (PRODUCT_STRING_LENGTH + 1) * sizeof (CHAR16);

> > +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);

> > +      if (Descriptor == NULL) {

> > +        return EFI_OUT_OF_RESOURCES;

> > +      }

> > +      Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16);

> > +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;

> > +      DwUsb->GetProduct (Descriptor->String, &Descriptor->Length);

> > +      ResponseSize = Descriptor->Length;

> > +      ResponseData = Descriptor;

> > +      break;

> > +    case 3:

> > +      DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +

> > +                       SERIAL_STRING_LENGTH * sizeof (CHAR16) + 1;

> > +      Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);

> > +      if (Descriptor == NULL) {

> > +        return EFI_OUT_OF_RESOURCES;

> > +      }

> > +      Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16);

> > +      Descriptor->DescriptorType = USB_DESC_TYPE_STRING;

> > +      DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length);

> > +      ResponseSize = Descriptor->Length;

> > +      ResponseData = Descriptor;

> > +      break;

> > +    }

> > +    break;

> > +  default:

> > +    DEBUG ((

> > +      DEBUG_INFO,

> > +      "DwUsbDxe: Didn't understand request for descriptor 0x%04x\n",

> > +      Request->Value

> > +      ));

> > +    return EFI_INVALID_PARAMETER;

> > +  }

> > +

> > +  //

> > +  // Send the response

> > +  //

> > +  if (Request->Length < ResponseSize) {

> > +    //

> > +    // Truncate response

> > +    //

> > +    ResponseSize = Request->Length;

> > +  } else if (Request->Length > ResponseSize) {

> > +    DEBUG ((DEBUG_INFO, "DwUsbDxe: Info: ResponseSize < wLength\n"));

> > +  }

> > +

> > +  EndPointTx (ENDPOINT0, ResponseData, ResponseSize);

> > +  if (Descriptor) {

> > +    FreePool (Descriptor);

> > +  }

> > +

> > +  return EFI_SUCCESS;

> > +}

> > +

> > +STATIC

> > +EFI_STATUS

> > +HandleSetAddress (

> > +  IN USB_DEVICE_REQUEST  *Request

> > +  )

> > +{

> > +  UINT32                 Data;

> > +

> > +  //

> > +  // Pretty confused if bmRequestType is anything but this:

> > +  //

> > +  if (Request->RequestType != USB_DEV_SET_ADDRESS_REQ_TYPE) {

> > +    return EFI_INVALID_PARAMETER;

> > +  }

> > +  DEBUG ((DEBUG_INFO, "DwUsbDxe: Setting address to %d\n", Request->Value));

> > +  ResetEndpoints ();

> > +

> > +  Data = READ_REG32 (DCFG);

> > +  Data &= ~DCFG_DEVADDR_MASK;

> > +  Data |= DCFG_DEVADDR (Request->Value);

> > +  WRITE_REG32 (DCFG, Data);

> > +  EndPointTx (ENDPOINT0, NULL, 0);

> > +

> > +  return EFI_SUCCESS;

> > +}

> > +

> > +STATIC

> > +VOID

> > +UsbDrvRequestEndpoint (

> > +  IN UINTN           Type,

> > +  IN UINTN           Dir

> > +  )

> > +{

> > +  UINTN              EndPoint = 1;

> > +  UINTN              NewBits;

> > +  UINT32             Data;

> > +

> > +  NewBits = DXEPCTL_EPTYPE (Type) | BIT28;

> > +

> > +  /*

> > +   * (Type << 18):Endpoint Type (EPType)

> > +   * 0x10000000:Endpoint Enable (EPEna)

> > +   * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.

> > +   * (ep<<22):TxFIFO Number (TxFNum)

> > +   * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.

> > +   */

> > +  if (Dir == DIR_IN) {  // IN: to host

> > +    Data = READ_REG32 (DIEPCTL (EndPoint));

> > +    Data &= ~DXEPCTL_EPTYPE_MASK;

> > +    Data |= NewBits | DXEPCTL_TXFNUM (EndPoint) | DXEPCTL_NAKSTS;

> > +    WRITE_REG32 (DIEPCTL (EndPoint), Data);

> > +  } else {    // OUT: to device

> > +    Data = READ_REG32 (DOEPCTL (EndPoint));

> > +    Data &= ~DXEPCTL_EPTYPE_MASK;

> > +    Data |= NewBits;

> > +    WRITE_REG32 (DOEPCTL (EndPoint), Data);

> > +  }

> > +}

> > +

> > +STATIC

> > +EFI_STATUS

> > +HandleSetConfiguration (

> > +  IN USB_DEVICE_REQUEST  *Request

> > +  )

> > +{

> > +  UINT32                 Data;

> > +

> > +  if (Request->RequestType != USB_DEV_SET_CONFIGURATION_REQ_TYPE) {

> > +    return EFI_INVALID_PARAMETER;

> > +  }

> > +

> > +  //

> > +  // Cancel all transfers

> > +  //

> > +  ResetEndpoints ();

> > +

> > +  UsbDrvRequestEndpoint (2, DIR_OUT);

> > +  UsbDrvRequestEndpoint (2, DIR_IN);

>

> What is 2?

>

I'll add comment onit.

> > +

> > +  Data = READ_REG32 (DIEPCTL1);

> > +  WRITE_REG32 (DIEPCTL1, Data | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11);

>

> Please give #defines for those named bits (or the whole command if

> more appropriate).

>

OK

> > +

> > +  /* Enable interrupts on all endpoints */

> > +  WRITE_REG32 (DAINTMSK, ~0);

> > +

> > +  EndPointRx (ENDPOINT1, CMD_SIZE);

> > +  EndPointTx (ENDPOINT0, NULL, 0);

> > +  return EFI_SUCCESS;

> > +}

> > +

> > +

> > +STATIC

> > +EFI_STATUS

> > +HandleDeviceRequest (

> > +  IN USB_DEVICE_REQUEST  *Request

> > +  )

> > +{

> > +  EFI_STATUS  Status;

> > +

> > +  switch (Request->Request) {

> > +  case USB_DEV_GET_DESCRIPTOR:

> > +    Status = HandleGetDescriptor (Request);

> > +    break;

> > +  case USB_DEV_SET_ADDRESS:

> > +    Status = HandleSetAddress (Request);

> > +    break;

> > +  case USB_DEV_SET_CONFIGURATION:

> > +    Status = HandleSetConfiguration (Request);

> > +    break;

> > +  default:

> > +    DEBUG ((DEBUG_ERROR,

> > +      "Didn't understand RequestType 0x%x Request 0x%x\n",

> > +      Request->RequestType, Request->Request));

> > +      Status = EFI_INVALID_PARAMETER;

> > +    break;

> > +  }

> > +

> > +  return Status;

> > +}

> > +

> > +STATIC

> > +VOID

> > +HandleEndPointInEvent (

> > +  VOID

> > +  )

> > +{

> > +  UINT32              EndPointInts;

> > +

> > +  EndPointInts = READ_REG32 (DIEPINT0);

> > +  WRITE_REG32 (DIEPINT0, EndPointInts);

> > +  if (EndPointInts & DXEPINT_XFERCOMPL) {

> > +    DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0)));

> > +  }

> > +

> > +  EndPointInts = READ_REG32 (DIEPINT1);

> > +  WRITE_REG32 (DIEPINT1, EndPointInts);

> > +  if (EndPointInts & DXEPINT_XFERCOMPL) {

> > +    DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n"));

> > +  }

> > +}

> > +

> > +STATIC

> > +VOID

> > +HandleEndPointOutEvent (

> > +  VOID

> > +  )

> > +{

> > +  UINT32              EndPointInts;

> > +  UINT32              Data;

> > +

> > +  /*

> > +   * indicates the status of an endpoint

> > +   * with respect to USB- and AHB-related events.

> > +   */

> > +  EndPointInts = READ_REG32 (DOEPINT0);

> > +  if (EndPointInts) {

> > +    WRITE_REG32 (DOEPINT0, EndPointInts);

> > +    if (EndPointInts & DXEPINT_XFERCOMPL) {

> > +      DEBUG ((DEBUG_INFO, "INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32 (DOEPTSIZ0)));

> > +    }

> > +    /*

> > +     *

> > +     * IN Token Received When TxFIFO is Empty (INTknTXFEmp)

> > +     * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)

> > +     * was empty. This interrupt is asserted on the endpoint for which the IN token

> > +     * was received.

> > +     */

> > +    if (EndPointInts & BIT3) { /* SETUP phase done */

>

> What is BIT3?

>

I'll try to add comment or use macro definition.

> > +      Data = READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK;

> > +      WRITE_REG32 (DIEPCTL0, Data);

> > +      Data = READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK;

> > +      WRITE_REG32 (DOEPCTL0, Data);

> > +      /* clear IN EP intr */

> > +      WRITE_REG32 (DIEPINT0, ~0);

> > +      HandleDeviceRequest((USB_DEVICE_REQUEST *)gCtrlReq);

> > +    }

> > +

> > +    /* Make sure EP0 OUT is set up to accept the next request */

> > +    WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));

> > +    /*

> > +     * IN Token Received When TxFIFO is Empty (INTknTXFEmp)

> > +     * Indicates that an IN token was received when the associated

> > +     * TxFIFO (periodic/nonperiodic) * was empty. This interrupt is

> > +     * asserted on the endpoint for which the IN token was received.

> > +     */

> > +    gDmaDescEp0->status.b.bs = 0x3;

> > +    gDmaDescEp0->status.b.mtrf = 0;

> > +    gDmaDescEp0->status.b.sr = 0;

> > +    gDmaDescEp0->status.b.l = 1;

> > +    gDmaDescEp0->status.b.ioc = 1;

> > +    gDmaDescEp0->status.b.sp = 0;

> > +    gDmaDescEp0->status.b.bytes = 64;

> > +    gDmaDescEp0->buf = (UINT32)(UINTN)gCtrlReq;

> > +    gDmaDescEp0->status.b.sts = 0;

> > +    gDmaDescEp0->status.b.bs = 0x0;

>

> Need some #defines for those numbers.

>

OK

> > +    WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)gDmaDescEp0);

> > +    //

> > +    // endpoint enable; clear NAK

> > +    //

> > +    WRITE_REG32 (DOEPCTL0, DXEPCTL_EPENA | DXEPCTL_CNAK);

> > +  }

> > +

> > +  EndPointInts = (READ_REG32 (DOEPINT1));

> > +  if (EndPointInts) {

> > +    WRITE_REG32 (DOEPINT1, EndPointInts);

> > +    /* Transfer Completed Interrupt (XferCompl);Transfer completed */

> > +    if (EndPointInts & DXEPINT_XFERCOMPL) {

> > +

> > +      UINTN Bytes = RxDescBytes - gDmaDesc->status.b.bytes;

> > +      UINTN Len = 0;

> > +

> > +      ArmDataSynchronizationBarrier ();

>

> MemoryFence ()?

>

OK

> > +      if (MATCH_CMD_LITERAL ("download", RxBuf)) {

> > +        mNumDataBytes = AsciiStrHexToUint64 (RxBuf + sizeof ("download"));

> > +      } else {

> > +        if (mNumDataBytes != 0) {

> > +          mNumDataBytes -= Bytes;

> > +        }

> > +      }

> > +

> > +      mDataReceivedCallback (Bytes, RxBuf);

> > +

> > +      if (mNumDataBytes == 0) {

> > +        Len = CMD_SIZE;

> > +      } else if (mNumDataBytes > DATA_SIZE) {

> > +        Len = DATA_SIZE;

> > +      } else {

> > +        Len = mNumDataBytes;

> > +      }

> > +

> > +      EndPointRx (ENDPOINT1, Len);

> > +    }

> > +  }

> > +}

> > +

> > +//

> > +// Instead of actually registering interrupt handlers, we poll the controller's

> > +// interrupt source register in this function.

> > +//

> > +STATIC

> > +VOID

> > +CheckInterrupts (

> > +  IN EFI_EVENT        Event,

> > +  IN VOID            *Context

> > +  )

> > +{

> > +  UINT32              Ints;

>

> "Ints" gets a bit confusing in C. Please write it out as interrupts.

>

OK

> > +  UINT32              Data;

> > +

> > +  //

> > +  // interrupt register

> > +  //

> > +  Ints = READ_REG32 (GINTSTS);

> > +

> > +  /*

> > +   * bus reset

> > +   * The core sets this bit to indicate that a reset is detected on the USB.

> > +   */

> > +  if (Ints & GINTSTS_USBRST) {

> > +    WRITE_REG32 (DCFG, DCFG_DESCDMA | DCFG_NZ_STS_OUT_HSHK);

> > +    ResetEndpoints ();

> > +  }

> > +

> > +  /*

> > +   * enumeration done, we now know the speed

> > +   * The core sets this bit to indicate that speed enumeration is complete. The

> > +   * application must read the Device Status (DSTS) register to obtain the

> > +   * enumerated speed.

> > +   */

> > +  if (Ints & GINTSTS_ENUMDONE) {

> > +    /* Set up the maximum packet sizes accordingly */

> > +    UINTN MaxPacket = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : MAX_PACKET_SIZE_CONTROL;

>

> Too long lines. Also an initializer from a ternary.

> Please split definition from assignment.

>

OK

> > +    //

> > +    // Set Maximum In Packet Size (MPS)

> > +    //

> > +    Data = READ_REG32 (DIEPCTL1);

> > +    Data &= ~DXEPCTL_MPS_MASK;

> > +    Data |= MaxPacket;

> > +    WRITE_REG32 (DIEPCTL1, Data);

> > +    //

> > +    //Set Maximum Out Packet Size (MPS)

> > +    //

> > +    Data = READ_REG32 (DOEPCTL1);

> > +    Data &= ~DXEPCTL_MPS_MASK;

> > +    Data |= MaxPacket;

> > +    WRITE_REG32 (DOEPCTL1, Data);

> > +  }

> > +

> > +  /*

> > +   * IN EP event

> > +   * The core sets this bit to indicate that an interrupt is pending on one of the IN

> > +   * endpoInts of the core (in Device mode). The application must read the

> > +   * Device All EndpoInts Interrupt (DAINT) register to determine the exact

> > +   * number of the IN endpoint on which the interrupt occurred, and then read

> > +   * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to

> > +   * determine the exact cause of the interrupt. The application must clear the

> > +   * appropriate status bit in the corresponding DIEPINTn register to clear this bit.

> > +   */

> > +  if (Ints & GINTSTS_IEPINT) {

> > +    HandleEndPointInEvent ();

> > +  }

> > +

> > +  /*

> > +   * OUT EP event

> > +   * The core sets this bit to indicate that an interrupt is pending on one of the

> > +   * OUT endpoints of the core (in Device mode). The application must read the

> > +   * Device All EndpoInts Interrupt (DAINT) register to determine the exact

> > +   * number of the OUT endpoint on which the interrupt occurred, and then read

> > +   * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register

> > +   * to determine the exact cause of the interrupt. The application must clear the

> > +   * appropriate status bit in the corresponding DOEPINTn register to clear this bit.

> > +   */

>

> Long lines in comments above, please rewrap.

>

OK

> > +  if (Ints & GINTSTS_OEPINT) {

> > +    HandleEndPointOutEvent ();

> > +  }

> > +

> > +  //

> > +  // clear ints

> > +  //

> > +  WRITE_REG32 (GINTSTS, Ints);

> > +}

> > +

> > +EFI_STATUS

> > +DwUsbSend (

> > +  IN        UINT8  EndpointIndex,

> > +  IN        UINTN  Size,

> > +  IN  CONST VOID  *Buffer

> > +  )

> > +{

> > +    EndPointTx (EndpointIndex, Buffer, Size);

> > +    return EFI_SUCCESS;

> > +}

> > +

> > +STATIC

> > +VOID

> > +DwUsbInit (

> > +  VOID

> > +  )

> > +{

> > +  VOID          *Buf;

> > +  UINT32        Data;

> > +  EFI_STATUS    Status;

> > +

> > +  Status = DmaAllocateBuffer (

> > +             EfiBootServicesData,

> > +             DWUSB_BUFFER_PAGE_NUM,

> > +             (VOID *)&Buf

> > +             );

> > +  if (EFI_ERROR (Status)) {

> > +    return;

> > +  }

> > +  gDmaDesc = Buf;

> > +  gDmaDescEp0 = gDmaDesc + sizeof (DwUsbDevDmaDesc);

> > +  gDmaDescIn = gDmaDescEp0 + sizeof (DwUsbDevDmaDesc);

> > +  gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (DwUsbDevDmaDesc);

> > +

> > +  ZeroMem (Buf, EFI_PAGE_SIZE * DWUSB_BUFFER_PAGE_NUM);

> > +

> > +  /* Reset usb controller.*/

> > +  /* Wait for OTG AHB master idle */

> > +  do {

> > +    Data = READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE;

> > +  } while (Data == 0);

> > +

> > +  /* OTG: Assert Software Reset */

> > +  WRITE_REG32 (GRSTCTL, GRSTCTL_CSFTRST);

> > +

> > +  /* Wait for OTG to ack reset */

> > +  while ((READ_REG32 (GRSTCTL) & GRSTCTL_CSFTRST) == GRSTCTL_CSFTRST);

> > +

> > +  /* Wait for OTG AHB master idle */

> > +  while ((READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE) == 0);

> > +

> > +  WRITE_REG32 (GDFIFOCFG, DATA_FIFO_CONFIG);

> > +  WRITE_REG32 (GRXFSIZ, RX_SIZE);

> > +  WRITE_REG32 (GNPTXFSIZ, ENDPOINT_TX_SIZE);

> > +  WRITE_REG32 (DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);

> > +  WRITE_REG32 (DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2);

> > +  WRITE_REG32 (DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3);

> > +  WRITE_REG32 (DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4);

> > +  WRITE_REG32 (DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5);

> > +  WRITE_REG32 (DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6);

> > +  WRITE_REG32 (DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7);

> > +  WRITE_REG32 (DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8);

> > +  WRITE_REG32 (DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9);

> > +  WRITE_REG32 (DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10);

> > +  WRITE_REG32 (DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11);

> > +  WRITE_REG32 (DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12);

> > +  WRITE_REG32 (DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13);

> > +  WRITE_REG32 (DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14);

> > +  WRITE_REG32 (DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15);

> > +

> > +  /*

> > +   * set Periodic TxFIFO Empty Level,

> > +   * Non-Periodic TxFIFO Empty Level,

> > +   * Enable DMA, Unmask Global Intr

> > +   */

> > +  WRITE_REG32 (GAHBCFG, GAHBCFG_CTRL_MASK);

> > +

> > +  /*select 8bit UTMI+, ULPI Inerface*/

> > +  WRITE_REG32 (GUSBCFG, GUSBCFG_USBTRDTIM_8BIT);

> > +

> > +  /* Detect usb work mode,host or device? */

> > +  do {

> > +    Data = READ_REG32 (GINTSTS);

> > +  } while (Data & GINTSTS_CURMODE_HOST);

> > +

> > +  /* Init global and device mode csr register. */

> > +  /* set Non-Zero-Length status out handshake */

> > +  Data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK;

>

> Why 0x20?

>


I'll add comment on it.

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