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