Message ID | 1534761085-26972-3-git-send-email-haojian.zhuang@linaro.org |
---|---|
State | New |
Headers | show |
Series | add DwUsb3Dxe driver | expand |
On Mon, Aug 20, 2018 at 06:31:25PM +0800, Haojian Zhuang wrote: > Add Designware USB 3.0 device driver. It's focus on USB device > functionality, not USB Host functionality. The USB driver is > mainly used for Android Fastboot application. > > Cc: Leif Lindholm <leif.lindholm@linaro.org> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> > --- > EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec | 44 + > EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf | 52 + > EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h | 632 +++++ > EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c | 2434 ++++++++++++++++++++ > 4 files changed, 3162 insertions(+) > > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec > new file mode 100644 > index 000000000000..038e4881a948 > --- /dev/null > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec > @@ -0,0 +1,44 @@ > +#/** @file > +# Framework Module Development Environment Industry Standards Please change this to reflect this package rather than EmbeddedPkg one (which appears to have stolen it from an old version of MdePkg.dec :) > +# > +# This Package provides headers and libraries that conform to EFI/PI Industry standards. > +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> > +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR> I see no need to keep these copyright statements. > +# Copyright (c) 2018, Linaro. All rights reserved.<BR> > +# > +# This program and the accompanying materials are licensed and made available under > +# the terms and conditions of the BSD License which accompanies this distribution. > +# The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +# > +#**/ > + > +[Defines] > + DEC_SPECIFICATION = 0x00010019 > + PACKAGE_NAME = DwUsb3DxePkg > + PACKAGE_GUID = 9b7aa6fe-405b-4955-af1f-5faf183aedec > + PACKAGE_VERSION = 0.1 > + > + > +################################################################################ > +# > +# Include Section - list of Include Paths that are provided by this package. > +# Comments are used for Keywords and Module Types. > +# > +# Supported Module Types: > +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION > +# > +################################################################################ > + > +[Guids.common] > + gDwUsb3DxeTokenSpaceGuid = { 0x098a50d3, 0x92e2, 0x461a, { 0xb6, 0xba, 0xf8, 0x5d, 0x9d, 0x89, 0x49, 0xf5 }} > + > +[Protocols.common] > + gDwUsbProtocolGuid = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }} Please make this file a common .dec for DwUsb and DwUsb3 instead of duplicating guid information. (If we weren't moving it to edk2-platforms, it would still have been better to add it to EmbeddedPkg.dec.) > + > +[PcdsFixedAtBuild.common] > + # DwUsb Driver PCDs > + gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress|0x0|UINT32|0x00000001 > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf > new file mode 100644 > index 000000000000..510b51a34de7 > --- /dev/null > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf > @@ -0,0 +1,52 @@ > +#/** @file > +# > +# Copyright (c) 2018, Linaro Limited. All rights reserved. > +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the BSD License > +# which accompanies this distribution. The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +# > +# > +#**/ > + > +[Defines] > + INF_VERSION = 0x00010019 > + BASE_NAME = DwUsb3Dxe > + FILE_GUID = 0879cd34-c399-4315-9891-56024072e711 > + MODULE_TYPE = UEFI_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = DwUsb3EntryPoint > + > +[Sources.common] > + DwUsb3Dxe.c > + > +[LibraryClasses] > + CacheMaintenanceLib > + DebugLib > + DmaLib > + IoLib > + MemoryAllocationLib > + TimerLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UsbSerialNumberLib I don't see this library anywhere in the tree? > + > +[Protocols] > + gEfiDriverBindingProtocolGuid > + gUsbDeviceProtocolGuid > + > +[Packages] > + ArmPkg/ArmPkg.dec > + EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + > +[Pcd] > + gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress > + > +[Depex] > + TRUE > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h > new file mode 100644 > index 000000000000..92b610553169 > --- /dev/null > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h > @@ -0,0 +1,632 @@ > +/** @file > + > + Copyright (c) 2017, Linaro Limited. All rights reserved. > + > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the BSD License > + which accompanies this distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > + > +#ifndef __DW_USB3_DXE_H__ > +#define __DW_USB3_DXE_H__ DW -> DESIGNWARE (throughout). > + > +#define DW_USB3_BASE FixedPcdGet32 (PcdDwUsb3DxeBaseAddress) > + > +#define GSBUCFG0 (DW_USB3_BASE + 0xC100) > +#define GCTL (DW_USB3_BASE + 0xC110) > + > +#define GCTL_PWRDNSCALE_MASK (0x1FFF << 19) > +#define GCTL_PWRDNSCALE(x) (((x) & 0x1FFF) << 19) > +#define GCTL_U2RSTECN BIT16 > +#define GCTL_PRTCAPDIR_MASK (BIT13 | BIT12) > +#define GCTL_PRTCAPDIR_HOST BIT12 > +#define GCTL_PRTCAPDIR_DEVICE BIT13 > +#define GCTL_PRTCAPDIR_OTG (BIT13 | BIT12) > +#define GCTL_U2EXIT_LFPS BIT2 > + > +#define GUSB2PHYCFG(x) (DW_USB3_BASE + 0xC200 + (((x) & 0xF) << 2)) > + > +#define GUSB2PHYCFG_USBTRDTIM_MASK (0xF << 10) > +#define GUSB2PHYCFG_USBTRDTIM(x) (((x) & 0xF) << 10) > +#define GUSB2PHYCFG_SUSPHY BIT6 > + > +#define GUSB3PIPECTL(x) (DW_USB3_BASE + 0xC2C0 + (((x) & 0x3) << 2)) > + > +#define PIPECTL_DELAYP1TRANS BIT18 > +#define PIPECTL_SUSPEND_EN BIT17 > +#define PIPECTL_LFPS_FILTER BIT9 > +#define PIPECTL_TX_DEMPH_MASK (0x3 << 1) > +#define PIPECTL_TX_DEMPH(x) (((x) & 0x3) << 1) > + > +#define GTXFIFOSIZ(x) (DW_USB3_BASE + 0xC300 + (((x) & 0x1F) << 2)) > +#define GRXFIFOSIZ(x) (DW_USB3_BASE + 0xC380 + (((x) & 0x1F) << 2)) > + > +#define FIFOSIZ_ADDR(x) (((x) & 0xFFFF) << 16) > +#define FIFOSIZ_DEP(x) ((x) & 0xFFFF) > + > +#define GEVNTADRL(x) (DW_USB3_BASE + 0xC400 + (((x) & 0x1F) << 2)) > +#define GEVNTADRH(x) (DW_USB3_BASE + 0xC404 + (((x) & 0x1F) << 2)) > +#define GEVNTSIZ(x) (DW_USB3_BASE + 0xC408 + (((x) & 0x1F) << 2)) > + > +#define GEVNTSIZ_EVNTINTMASK BIT31 > +#define GEVNTSIZ_EVNTSIZ_MASK (0xFFFF) > +#define GEVNTSIZ_EVNTSIZ(x) ((x) & 0xFFFF) > + > +#define GEVNTCOUNT(x) (DW_USB3_BASE + 0xC40C + (((x) & 0x1F) << 2)) > +#define GEVNTCOUNT_EVNTCOUNT_MASK (0xFFFF) > +#define GEVNTCOUNT_EVNTCOUNT(x) ((x) & 0xFFFF) > + > +// Non-Endpoint specific event flag > +#define GEVNT_INTTYPE_MASK (0x7F << 1) > +#define GEVNT_INTTYPE(x) (((x) & 0x7F) << 1) > +#define EVENT_I2C_INT 4 > +#define EVENT_CARKIT_INT 3 > +#define EVENT_OTG_INT 1 > +#define EVENT_DEV_INT 0 > + > +#define GEVNT_NON_EP BIT0 > +// Endpoint specific event flag > +#define GEVNT_DEPEVT_INTTYPE_MASK (0xF << 6) > +#define GEVNT_DEPEVT_INTTYPE(x) (((x) & 0xF) << 6) > +#define GEVNT_DEPEVT_INTTYPE_EPCMD_CMPL (7 << 6) > +#define GEVNT_DEPEVT_INTTYPE_STRM_EVT (6 << 6) > +#define GEVNT_DEPEVT_INTTYPE_FIFOXRUN (4 << 6) > +#define GEVNT_DEPEVT_INTTYPE_XFER_NRDY (3 << 6) > +#define GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG (2 << 6) > +#define GEVNT_DEPEVT_INTTYPE_XFER_CMPL (1 << 6) > +#define GEVNT_DEPEVT_EPNUM_MASK (0x1F << 1) > +#define GEVNT_DEPEVT_EPNUM_SHIFT 1 > +#define GEVNT_DEPEVT_EPNUM(x) (((x) & 0x1F) << 1) > +// Devices specific event flag > +#define GEVNT_DEVT_MASK (0xF << 8) > +#define GEVNT_DEVT_SHIFT 8 > +#define GEVNT_DEVT(x) (((x) & 0xF) << 8) > +#define GEVNT_DEVT_INACT_TIMEOUT_RCVD (0x15 << 8) > +#define GEVNT_DEVT_VNDR_DEV_TST_RCVD (0x14 << 8) > +#define GEVNT_DEVT_OVERFLOW (0x13 << 8) > +#define GEVNT_DEVT_CMD_CMPL (0x12 << 8) > +#define GEVNT_DEVT_ERRATICERR (0x11 << 8) > +#define GEVNT_DEVT_SOF (0x7 << 8) > +#define GEVNT_DEVT_EOPF (0x6 << 8) > +#define GEVNT_DEVT_HIBER_REQ (0x5 << 8) > +#define GEVNT_DEVT_WKUP (0x4 << 8) > +#define GEVNT_DEVT_ULST_CHNG (0x3 << 8) > +#define GEVNT_DEVT_CONNDONE (0x2 << 8) > +#define GEVNT_DEVT_USBRESET (0x1 << 8) > +#define GEVNT_DEVT_DISCONN (0x0 << 8) > + > +#define DCFG (DW_USB3_BASE + 0xC700) > + > +#define DCFG_NUMP_MASK (0x1F << 17) > +#define DCFG_NUMP(x) (((x) & 0x1F) << 17) > +#define DCFG_DEVADDR_MASK (0x7F << 3) > +#define DCFG_DEVADDR(x) (((x) & 0x7F) << 3) > +#define DCFG_DEVSPD_MASK (0x7) > +#define DCFG_DEVSPD(x) ((x) & 0x7) > +#define DEVSPD_HS_PHY_30MHZ_OR_60MHZ 0 > +#define DEVSPD_FS_PHY_30MHZ_OR_60MHZ 1 > +#define DEVSPD_LS_PHY_6MHZ 2 > +#define DEVSPD_FS_PHY_48MHZ 3 > +#define DEVSPD_SS_PHY_125MHZ_OR_250MHZ 4 > + > +#define DCTL (DW_USB3_BASE + 0xC704) > + > +#define DCTL_RUN_STOP BIT31 > +#define DCTL_CSFTRST BIT30 > +#define DCTL_INIT_U2_EN BIT12 > +#define DCTL_ACCEPT_U2_EN BIT11 > +#define DCTL_INIT_U1_EN BIT10 > +#define DCTL_ACCEPT_U1_EN BIT9 > + > +#define DEVTEN (DW_USB3_BASE + 0xC708) > +#define DEVTEN_CONNECTDONEEN BIT2 > +#define DEVTEN_USBRSTEN BIT1 > +#define DEVTEN_DISCONNEN BIT0 > + > +#define DSTS (DW_USB3_BASE + 0xC70C) > +#define DSTS_GET_DEVSPD(x) ((x) & 0x7) > + > +#define DALEPENA (DW_USB3_BASE + 0xC720) > + > +#define DEPCMDPAR2(x) (DW_USB3_BASE + 0xC800 + ((x) & 0x1F) * 0x10) > +#define DEPCMDPAR1(x) (DW_USB3_BASE + 0xC804 + ((x) & 0x1F) * 0x10) > +#define DEPCMDPAR0(x) (DW_USB3_BASE + 0xC808 + ((x) & 0x1F) * 0x10) > +#define DEPCMD(x) (DW_USB3_BASE + 0xc80C + ((x) & 0x1F) * 0x10) > + > +#define DEPCMD_COMMANDPARAM_MASK (0xFFFF << 16) > +#define DEPCMD_COMMANDPARAM(x) (((x) & 0xFFFF) << 16) > +/* Stream Number or uFrame (input) */ > +#define DEPCMD_STR_NUM_OR_UF_MASK (0xFFFF << 16) > +#define DEPCMD_STR_NUM_OR_UF(x) (((x) & 0xFFFF) << 16) > +/* Transfer Resource Index (output) */ > +#define DEPCMD_XFER_RSRC_IDX_SHIFT 16 > +#define DEPCMD_XFER_RSRC_IDX_MASK (0x7F << 16) > +#define DEPCMD_XFER_RSRC_IDX(x) (((x) & 0x7F) << 16) > +#define GET_DEPCMD_XFER_RSRC_IDX(x) (((x) >> 16) & 0x7F) > +#define DEPCMD_CMDACT BIT10 > +#define DEPCMD_CMDTYPE_MASK 0xFF > +#define DEPCMD_CMDTYPE(x) ((x) & 0xFF) > + > +/* EP registers range as: OUT0, IN0, OUT1, IN1, ... */ > +#define EP_OUT_IDX(x) ((x) * 2) > +#define EP_IN_IDX(x) (((x) * 2) + 1) > + > +#define CMDTYPE_SET_EP_CFG 1 > +#define CMDTYPE_SET_XFER_CFG 2 > +#define CMDTYPE_GET_EP_STATE 3 > +#define CMDTYPE_SET_STALL 4 > +#define CMDTYPE_CLR_STALL 5 > +#define CMDTYPE_START_XFER 6 > +#define CMDTYPE_UPDATE_XFER 7 > +#define CMDTYPE_END_XFER 8 > +#define CMDTYPE_START_NEW_CFG 9 > + > +#define EPTYPE_CONTROL 0 > +#define EPTYPE_ISOC 1 > +#define EPTYPE_BULK 2 > +#define EPTYPE_INTR 3 > + > +#define CFG_ACTION_INIT 0 > +#define CFG_ACTION_RESTORE 1 > +#define CFG_ACTION_MODIFY 2 > + > +#define EPCFG0_CFG_ACTION_MASK (0x3 << 30) > +#define EPCFG0_CFG_ACTION(x) (((x) & 0x3) << 30) > +#define EPCFG0_BRSTSIZ_MASK (0xF << 22) > +#define EPCFG0_BRSTSIZ(x) (((x) & 0xF) << 22) > +#define EPCFG0_TXFNUM_MASK (0x1F << 17) > +#define EPCFG0_TXFNUM(x) (((x) & 0x1F) << 17) > +#define EPCFG0_MPS_MASK (0x7FF << 3) > +#define EPCFG0_MPS(x) (((x) & 0x7FF) << 3) > +#define EPCFG0_EPTYPE_MASK (0x3 << 1) > +#define EPCFG0_EPTYPE_SHIFT 1 > +#define EPCFG0_EPTYPE(x) (((x) & 0x3) << 1) > + > +/* Endpoint Number */ > +#define EPCFG1_EP_NUM_MASK (0xF << 26) > +#define EPCFG1_EP_NUM(x) (((x) & 0xF) << 26) > +/* Endpoint Direction */ > +#define EPCFG1_EP_DIR_IN BIT25 > +/* Stream Not Ready */ > +#define EPCFG1_XFER_NRDY BIT10 > +/* XferInProgress Enable */ > +#define EPCFG1_XFER_IN_PROG BIT9 > +/* Stream Completed */ > +#define EPCFG1_XFER_CMPL BIT8 > + > +#define USB_SPEED_UNKNOWN 0 > +#define USB_SPEED_LOW 1 > +#define USB_SPEED_FULL 2 > +#define USB_SPEED_HIGH 3 > +#define USB_SPEED_VARIABLE 4 > +#define USB_SPEED_SUPER 5 > + > +// DMA registers > +#define DSCSTS_TRBRSP_MASK (0xF << 28) > +#define DSCSTS_TRBRSP(x) (((x) & 0xF) << 28) > +#define GET_DSCSTS_TRBRSP(x) (((x) >> 28) & 0xF) > +#define TRBRSP_MISSED_ISOC_IN 1 > +#define TRBRSP_SETUP_PEND 2 > +#define TRBRSP_XFER_IN_PROG 4 > +#define DSCSTS_PCM1_MASK (0x3 << 24) > +#define DSCSTS_PCM1(x) (((x) & 0x3) << 24) > +#define DSCSTS_XFERCNT_MASK 0xFFFFFF > +#define DSCSTS_XFERCNT(x) ((x) & 0xFFFFFF) > +#define GET_DSCSTS_XFERCNT(x) ((x) & 0xFFFFFF) > + > +#define DSCCTL_STRMID_SOFN(x) (((x) & 0xFFFF) << 14) > +#define DSCCTL_IOC BIT11 > +#define DSCCTL_ISP BIT10 > +#define DSCCTL_TRBCTL_MASK (0x3F << 4) > +#define DSCCTL_TRBCTL(x) (((x) & 0x3F) << 4) > +#define DSCCTL_LST BIT1 > +#define DSCCTL_HWO BIT0 > +#define TRBCTL_NORMAL 1 > +#define TRBCTL_SETUP 2 > +#define TRBCTL_STATUS_2 3 > +#define TRBCTL_STATUS_3 4 > +#define TRBCTL_CTLDATA_1ST 5 > +#define TRBCTL_ISOC_1ST 6 > +#define TRBCTL_ISOC 7 > +#define TRBCTL_LINK 8 > +#define TRBCTL_NORMAL_ZLP 9 > + > + > +#define UE_DIR_IN 0x80 > +#define UE_DIR_OUT 0 > +#define UE_SET_DIR(a, d) ((a) | (((d) & 1) << 7)) > +#define UE_GET_DIR(a) ((a) & 0x80) > +#define UE_ADDR 0x0F > +#define UE_GET_ADDR(a) ((a) & UE_ADDR) > + > +#define UT_GET_DIR(a) ((a) & 0x80) > +#define UT_WRITE 0x00 > +#define UT_READ 0x80 > + > +#define UT_GET_TYPE(a) ((a) & 0x60) > +#define UT_STANDARD 0x00 > +#define UT_CLASS 0x20 > +#define UT_VENDOR 0x40 > + > +#define UT_GET_RECIPIENT(a) ((a) & 0x1f) > +#define UT_DEVICE 0x00 > +#define UT_INTERFACE 0x01 > +#define UT_ENDPOINT 0x02 > +#define UT_OTHER 0x03 > + > +#define UR_GET_STATUS 0x00 > +#define UR_CLEAR_FEATURE 0x01 > +#define UR_SET_FEATURE 0x03 > +#define UR_SET_ADDRESS 0x05 > +#define UR_GET_DESCRIPTOR 0x06 > +#define UR_SET_DESCRIPTOR 0x07 > +#define UR_GET_CONFIG 0x08 > +#define UR_SET_CONFIG 0x09 > +#define UR_GET_INTERFACE 0x0A > +#define UR_SET_INTERFACE 0x0B > +#define UR_SYNCH_FRAME 0x0C > +#define UR_SET_SEL 0x30 > +#define UR_SET_ISOC_DELAY 0x31 > + Somewhere around here starts a bunch of redefinitions of things already described in MdePkg/Include/IndustryStandard/Usb.h. Can you please reuse that include file as much as possible. > +/* Feature numbers */ > +#define UF_ENDPOINT_HALT 0 > +#define UF_DEVICE_REMOTE_WAKEUP 1 > +#define UF_TEST_MODE 2 > +#define UF_DEVICE_B_HNP_ENABLE 3 > +#define UF_DEVICE_A_HNP_SUPPORT 4 > +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 > +#define UF_FUNCTION_SUSPEND 0 > +#define UF_U1_ENABLE 48 > +#define UF_U2_ENABLE 49 > +#define UF_LTM_ENABLE 50 > + > +#define UDESC_DEVICE 0x01 > +#define UDESC_CONFIG 0x02 > +#define UDESC_STRING 0x03 > +#define UDESC_INTERFACE 0x04 > +#define UDESC_ENDPOINT 0x05 > +#define UDESC_SS_USB_COMPANION 0x30 > +#define UDESC_DEVICE_QUALIFIER 0x06 > +#define UDESC_BOS 0x0f > +#define UDESC_DEVICE_CAPABILITY 0x10 > + > +#define STRING_LANGUAGE 0 > +#define STRING_MANUFACTURER 1 > +#define STRING_PRODUCT 2 > +#define STRING_SERIAL 3 > + > +#define CONFIG_VALUE 1 > + > +#define USB3_BULK_IN_EP 1 > +#define USB3_BULK_OUT_EP 1 > + > +#define USB_ENUM_ADB_PORT_VID 0x18D1 > +#define USB_ENUM_ADB_PORT_PID 0xD00D > +#define USB_ENUM_INTERFACE_ADB_SUBCLASS 0x42 > +#define USB_ENUM_INTERFACE_ADB_PROTOCOL 0x03 > + > +struct usb3_pcd; > + > +typedef enum pcd_state { > + USB3_STATE_UNCONNECTED, /* no host */ > + USB3_STATE_DEFAULT, > + USB3_STATE_ADDRESSED, > + USB3_STATE_CONFIGURED, > +} pcdstate_e; These structs also break the coding style completely. Will using IndustryStandard/Usb.h get rid of all of that? > + > +typedef enum ep0_state { > + EP0_IDLE, > + EP0_IN_DATA_PHASE, > + EP0_OUT_DATA_PHASE, > + EP0_IN_WAIT_NRDY, > + EP0_OUT_WAIT_NRDY, > + EP0_IN_STATUS_PHASE, > + EP0_OUT_STATUS_PHASE, > + EP0_STALL, > +} ep0state_e; > + > +typedef struct usb3_dma_desc { > + /** Buffer Pointer - Low address quadlet */ > + UINT32 bptl; > + > + /** Buffer Pointer - High address quadlet */ > + UINT32 bpth; > + > + /** Status quadlet. Fields defined in enum @ref desc_sts_data. */ > + UINT32 status; > + > + /** Control quadlet. Fields defined in enum @ref desc_ctl_data. */ > + UINT32 control; > +} usb3_dma_desc_t; > + > +typedef struct usb3_pcd_req { > + usb3_dma_desc_t *trb; > + UINT64 trbdma; > + > + UINT32 length; > + UINT32 actual; > + > + UINT64 *bufdma; > + int (*complete)(unsigned actual, int status); > +} usb3_pcd_req_t; > + > +typedef struct usb_device_request { > + UINT8 bmRequestType; > + UINT8 bRequest; > + UINT16 wValue; > + UINT16 wIndex; > + UINT16 wLength; > +} usb_device_request_t; > + > +#pragma pack(1) > +/** USB_DT_DEVICE: Device descriptor */ > +typedef struct usb_device_descriptor { > + UINT8 bLength; > + UINT8 bDescriptorType; > + > + UINT16 bcdUSB; > +#define USB_CLASS_COMM 0x02 > +#define USB_CLASS_VENDOR_SPEC 0xFF > +#define USB_SC_VENDOR_SPEC 0xFF > +#define USB_PR_VENDOR_SPEC 0xFF > + UINT8 bDeviceClass; > + UINT8 bDeviceSubClass; > + UINT8 bDeviceProtocol; > + UINT8 bMaxPacketSize0; > + UINT16 idVendor; > + UINT16 idProduct; > + UINT16 bcdDevice; > + UINT8 iManufacturer; > + UINT8 iProduct; > + UINT8 iSerialNumber; > + UINT8 bNumConfigurations; > +} usb_device_descriptor_t; > + > +/* USB_DT_CONFIG: Config descriptor */ > +typedef struct usb_config_descriptor { > + UINT8 bLength; > + UINT8 bDescriptorType; > + > + UINT16 wTotalLength; > + UINT8 bNumInterfaces; > +#define CONFIG_VALUE 1 > + UINT8 bConfigurationValue; > + UINT8 iConfiguration; > +#define USB_CONFIG_ATT_ONE (1 << 7) > + UINT8 bmAttributes; > +#define USB_CONFIG_VBUS_DRAW (0xFA) > + UINT8 bMaxPower; > +} usb_config_descriptor_t; > + > +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ > +typedef struct usb_qualifier_descriptor { > + UINT8 bLength; > + UINT8 bDescriptorType; > + > + UINT16 bcdUSB; > + UINT8 bDeviceClass; > + UINT8 bDeviceSubClass; > + UINT8 bDeviceProtocol; > + UINT8 bMaxPacketSize0; > + UINT8 bNumConfigurations; > + UINT8 bRESERVED; > +} usb_qualifier_descriptor_t; > + > +/* USB_DT_INTERFACE: Interface descriptor */ > +typedef struct usb_interface_descriptor { > + UINT8 bLength; > + UINT8 bDescriptorType; > + > + UINT8 bInterfaceNumber; > + UINT8 bAlternateSetting; > + UINT8 bNumEndpoints; > + UINT8 bInterfaceClass; > + UINT8 bInterfaceSubClass; > + UINT8 bInterfaceProtocol; > + UINT8 iInterface; > +} usb_interface_descriptor_t; > + > +/* USB_DT_ENDPOINT: Endpoint descriptor */ > +typedef struct usb_endpoint_descriptor { > + UINT8 bLength; > + UINT8 bDescriptorType; > + > + UINT8 bEndpointAddress; > + UINT8 bmAttributes; > +#define USB_ENDPOINT_XFER_CONTROL 0x00 > +#define USB_ENDPOINT_XFER_ISOC 0x01 > +#define USB_ENDPOINT_XFER_BULK 0x02 > +#define USB_ENDPOINT_XFER_INT 0x03 > + UINT16 wMaxPacketSize; > + UINT8 bInterval; > +} usb_endpoint_descriptor_t; > + > +/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ > +typedef struct usb_ss_ep_comp_descriptor { > + UINT8 bLength; > + UINT8 bDescriptorType; > + > + UINT8 bMaxBurst; > + UINT8 bmAttributes; > + UINT16 wBytesPerInterval; > +} usb_ss_ep_comp_descriptor_t; > + > +/* WUSB BOS Descriptor (Binary device Object Store) */ > +typedef struct wusb_bos_desc { > + UINT8 bLength; > + UINT8 bDescriptorType; > + UINT16 wTotalLength; > + UINT8 bNumDeviceCaps; > +} wusb_bos_desc_t; > + > +#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 > +typedef struct usb_dev_cap_20_ext_desc { > + UINT8 bLength; > + UINT8 bDescriptorType; > + UINT8 bDevCapabilityType; > +#define USB_20_EXT_LPM 0x02 > + UINT32 bmAttributes; > +} usb_dev_cap_20_ext_desc_t; > + > +#define USB_DEVICE_CAPABILITY_SS_USB 0x03 > +typedef struct usb_dev_cap_ss_usb { > + UINT8 bLength; > + UINT8 bDescriptorType; > + UINT8 bDevCapabilityType; > +#define USB_DC_SS_USB_LTM_CAPABLE 0x02 > + UINT8 bmAttributes; > +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 > +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 > +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 > +#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 > + UINT32 wSpeedsSupported; > + UINT8 bFunctionalitySupport; > + UINT8 bU1DevExitLat; > + UINT32 wU2DevExitLat; > +} usb_dev_cap_ss_usb_t; > + > +#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 > +typedef struct usb_dev_cap_container_id { > + UINT8 bLength; > + UINT8 bDescriptorType; > + UINT8 bDevCapabilityType; > + UINT8 bReserved; > + UINT8 containerID[16]; > +} usb_dev_cap_container_id_t; > +#pragma pack() > + > +typedef union usb_setup_pkt { > + usb_device_request_t req; > + UINT32 d32[2]; > + UINT8 d8[8]; > +} usb_setup_pkt_t; > + > +typedef struct usb3_pcd_ep { > + struct usb3_pcd *pcd; > + > + UINT8 EpInIdx; > + UINT8 EpOutIdx; > + UINT8 phys; > + > + //UINT8 phys; > + UINT8 num; > + UINT8 type; > + UINT8 maxburst; > + UINT16 maxpacket; > + /* Tx FIFO # for IN EPs */ > + UINT8 tx_fifo_num; > + > + /* The Transfer Resource Index from the Start Transfer command */ > + UINT8 tri_out; > + UINT8 tri_in; > + > + UINT8 stopped; > + /* Send ZLP */ > + UINT8 send_zlp; > + /* True if 3-stage control transfer */ > + UINT8 three_stage; > + /* True if transfer has been started on EP */ > + UINT8 xfer_started; > + /* EP direction 0 = OUT */ > + UINT8 is_in; > + /* True if endpoint is active */ > + UINT8 active; > + /* Initial data pid of bulk endpoint */ > + UINT8 data_pid_start; > + > + /* ep_desc (excluding ep0) */ > + usb3_dma_desc_t *ep_desc; > + > +#if 0 > + /* TRB descriptor must be aligned to 16 bytes */ > + UINT8 epx_desc[32]; > +#endif > + > + /* request (excluding ep0) */ > + usb3_pcd_req_t req; > +} usb3_pcd_ep_t; > + > +typedef struct usb3_pcd { > + //struct usb3_device *usb3_dev; > + > + INT32 link_state; > + pcdstate_e state; > + UINT8 new_config; > + ep0state_e ep0state; > + > + UINT32 eps_enabled; > + UINT32 ltm_enable; > + > + usb3_pcd_ep_t ep0; > + usb3_pcd_ep_t out_ep; > + usb3_pcd_ep_t in_ep; > + > + /* > + usb3_dev_global_regs_t *dev_global_regs; > + usb3_dev_ep_regs_t *out_ep_regs; > + usb3_dev_ep_regs_t *in_ep_regs; > + */ > + > + usb3_pcd_req_t ep0_req; > + > + UINT8 speed; > + > + usb3_dma_desc_t *ep0_setup_desc; > + usb3_dma_desc_t *ep0_in_desc; > + usb3_dma_desc_t *ep0_out_desc; > + > + /* TRB descriptor must be aligned to 16 bytes */ > +#if 0 > + UINT8 ep0_setup[32]; > + UINT8 ep0_in[32]; > + UINT8 ep0_out[32]; > + > + usb_setup_pkt_t ep0_setup_pkt[5]; > + > +#define USB3_STATUS_BUF_SIZE 512 > + UINT8 ep0_status_buf[USB3_STATUS_BUF_SIZE]; > + > +#define USB3_BULK_BUF_SIZE 2048 > + UINT8 ss_bulk_buf[USB3_BULK_BUF_SIZE]; > +#endif > + > + UINT32 file_type; > + UINT32 file_address; > + UINT32 file_capacity; > + UINT32 file_total_frame; > + UINT32 file_curr_frame; > + UINT32 file_next_frame; > + UINT32 file_received; > + UINT32 file_complete; > + > + UINT16 test_mode_nr; > + UINT16 test_mode; > +} usb3_pcd_t; > + > +struct usb_enum_port_param { > + UINT16 idVendor; > + UINT16 idProduct; > + UINT8 bInterfaceSubClass; > + UINT8 bInterfaceProtocol; > +}; > + > +#if 0 If not used, leave it out. > +typedef struct usb3_pcd_req { > + usb3_dma_desc_t *trb; > + UINT64 trbdma; > + > + UINT32 length; > + UINT32 actual; > + > + UINT64 *bufdma; > + int (*complete)(unsigned actual, int status); > +} usb3_pcd_req_t; > + > +#endif > + > +#endif /* __DW_USB3_DXE_H__ */ > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c > new file mode 100644 > index 000000000000..83d5e4736de0 > --- /dev/null > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c > @@ -0,0 +1,2434 @@ > +/** @file > + > + Copyright (c) 2018, Linaro Limited. All rights reserved. > + > + This program and the accompanying materials are licensed and made available > + under the terms and conditions of the BSD License which accompanies this > + distribution. The full text of the license may be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + > +**/ > + > +#include <IndustryStandard/Usb.h> > +#include <Library/ArmLib.h> > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/CacheMaintenanceLib.h> > +#include <Library/DebugLib.h> > +#include <Library/DmaLib.h> > +#include <Library/IoLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/TimerLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiDriverEntryPoint.h> > +#include <Library/UefiRuntimeServicesTableLib.h> > +#include <Protocol/DwUsb.h> > +#include <Protocol/DriverBinding.h> > +#include <Protocol/UsbDevice.h> > + > +#include "DwUsb3Dxe.h" > + > +#define FIFO_DIR_TX 0 > +#define FIFO_DIR_RX 1 > + > +#define TX_FIFO_ADDR 0 > +#define RX_FIFO_ADDR 0 > + > +#define RAM_WIDTH 8 > +#define RAM_TX0_DEPTH 2048 > +#define RAM_TX1_DEPTH 4096 > +#define RAM_RX_DEPTH 8192 Should these not also go into DwUsb3Dxe.h? > + > +#define USB_TYPE_LENGTH 16 > +#define USB_BLOCK_HIGH_SPEED_SIZE 512 > +#define DATA_SIZE 131072 > +#define CMD_SIZE 512 What do the above definitions mean? > +#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1) This one does not appear to be used? > + > +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) Use available macros in Base.h. > + > +// > +// The time between interrupt polls, in units of 100 nanoseconds > +// 10 Microseconds > +// > +#define DW_INTERRUPT_POLL_PERIOD 100 > + > +#define DWUSB3_EVENT_BUF_SIZE 256 > + > +// > +// Maxpacket size for EP0, defined by USB3 spec > +// > +#define USB3_MAX_EP0_SIZE 512 > + > +// > +// Maxpacket size for any EP, defined by USB3 spec > +// > +#define USB3_MAX_PACKET_SIZE 1024 > +#define USB2_HS_MAX_PACKET_SIZE 512 > +#define USB2_FS_MAX_PACKET_SIZE 64 > + > +#define USB3_STATE_UNCONNECTED 0 > +#define USB3_STATE_DEFAULT 1 > +#define USB3_STATE_ADDRESSED 2 > +#define USB3_STATE_CONFIGURED 3 > + > +#define USB3_STATUS_BUF_SIZE 512 If these are defined by USB3 spec, please add them to MdePkg/Include/IndustryStandard/Usb.h instead of defining them locally. > + > +#define GET_EVENTBUF_COUNT() \ > + (GEVNTCOUNT_EVNTCOUNT (MmioRead32 (GEVNTCOUNT (0)))) > +#define UPDATE_EVENTBUF_COUNT(x) \ > + (MmioWrite32 (GEVNTCOUNT (0), GEVNTCOUNT_EVNTCOUNT (x))) > + > +#define SET_DEVADDR(x) \ > + (MmioAndThenOr32 (DCFG, ~DCFG_DEVADDR_MASK, DCFG_DEVADDR (x))) Should these not also move to DwUsb3Dxe.h? > + > +EFI_GUID gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID; This looks less than ideal - this makes it impossible to include DwUsb2 and DwUsb3 drivers in the same image. > + > +STATIC DW_USB_PROTOCOL *DwUsb; > + > +STATIC usb3_pcd_t gPcd; This seems a very unfortunate choice for variable name. > +STATIC UINT32 *gEventBuf, *gEventPtr; > +STATIC struct usb_device_descriptor gDwUsb3DevDesc; > +STATIC VOID *gRxBuf; > + > +STATIC usb_setup_pkt_t *gEndPoint0SetupPacket; > +STATIC UINT8 *gEndPoint0StatusBuf; Although most if not all of these will disappear when converting to UEFI driver model, why do they have 'g' prefix in the first place? 'g' is for globally visible symbols. Variables that are "global" in this file only are better off using 'm'. > +STATIC USB_DEVICE_RX_CALLBACK mDataReceivedCallback; > +STATIC UINTN mDataBufferSize; > + > +struct usb_interface_descriptor intf = { > + sizeof (struct usb_interface_descriptor), > + UDESC_INTERFACE, > + 0, > + 0, > + 2, > + USB_CLASS_VENDOR_SPEC, > + 0x42, > + 0x03, > + 0 > +}; > + > +const struct usb_ss_ep_comp_descriptor ep_comp = { > + sizeof (struct usb_ss_ep_comp_descriptor), > + UDESC_SS_USB_COMPANION, > + 0, > + 0, > + 0 > +}; > + > +const struct usb_endpoint_descriptor hs_bulk_in = { > + sizeof (struct usb_endpoint_descriptor), > + UDESC_ENDPOINT, > + UE_DIR_IN | USB3_BULK_IN_EP, > + USB_ENDPOINT_XFER_BULK, > + 0x200, > + 0 > +}; > + > +const struct usb_endpoint_descriptor > +hs_bulk_out = { > + sizeof(struct usb_endpoint_descriptor), /* bLength */ > + UDESC_ENDPOINT, /* bDescriptorType */ > + > + UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */ > + USB_ENDPOINT_XFER_BULK, /* bmAttributes */ > + 0x200, /* wMaxPacketSize: 512 of high-speed */ > + 1, /* bInterval */ > +}; > + > +const struct usb_endpoint_descriptor ss_bulk_in = { > + sizeof(struct usb_endpoint_descriptor), /* bLength */ > + UDESC_ENDPOINT, /* bDescriptorType */ > + > + UE_DIR_IN | USB3_BULK_IN_EP, /* bEndpointAddress */ > + USB_ENDPOINT_XFER_BULK, /* bmAttributes */ > + 0x400, /* wMaxPacketSize: 1024 of super-speed */ > + 0, /* bInterval */ > +}; > + > +const struct usb_endpoint_descriptor ss_bulk_out = { > + sizeof(struct usb_endpoint_descriptor), /* bLength */ > + UDESC_ENDPOINT, /* bDescriptorType */ > + > + UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */ > + USB_ENDPOINT_XFER_BULK, /* bmAttributes */ > + 0x400, /* wMaxPacketSize: 1024 of super-speed */ > + 0, /* bInterval */ > +}; > + > +/** The BOS Descriptor */ What's a BOS? > + > +const struct usb_dev_cap_20_ext_desc cap1 = { > + sizeof(struct usb_dev_cap_20_ext_desc), /* bLength */ > + UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ > + USB_DEVICE_CAPABILITY_20_EXTENSION, /* bDevCapabilityType */ > + 0x2, /* bmAttributes */ > +}; > + > +const struct usb_dev_cap_ss_usb > +cap2 = { > + sizeof(struct usb_dev_cap_ss_usb), /* bLength */ > + UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ > + USB_DEVICE_CAPABILITY_SS_USB, /* bDevCapabilityType */ > + 0x0, /* bmAttributes */ > + (USB_DC_SS_USB_SPEED_SUPPORT_SS | > + USB_DC_SS_USB_SPEED_SUPPORT_HIGH), /* wSpeedsSupported */ > + 0x2, /* bFunctionalitySupport */ > + 0xa, /* bU1DevExitLat */ > + 0x100, /* wU2DevExitLat */ > +}; > + > +const struct usb_dev_cap_container_id > +cap3 = { > + sizeof(struct usb_dev_cap_container_id),/* bLength */ > + UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ > + USB_DEVICE_CAPABILITY_CONTAINER_ID, /* bDevCapabilityType */ > + 0, /* bReserved */ > + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* containerID */ > +}; > + > +const struct wusb_bos_desc > +bos = { > + sizeof(struct wusb_bos_desc), /* bLength */ > + UDESC_BOS, /* bDescriptorType */ > + (sizeof(struct wusb_bos_desc) + \ > + sizeof(cap1) + sizeof(cap2) + \ > + sizeof(cap3)), /* wTotalLength */ > + 3, /* bNumDeviceCaps */ > +}; > + > +STATIC struct usb_enum_port_param usb_port_activity_config = { > + .idVendor = USB_ENUM_ADB_PORT_VID, > + .idProduct = USB_ENUM_ADB_PORT_PID, > + .bInterfaceSubClass = USB_ENUM_INTERFACE_ADB_SUBCLASS, > + .bInterfaceProtocol = USB_ENUM_INTERFACE_ADB_PROTOCOL > +}; > + > +STATIC > +UINT32 > +DwUsb3GetEventBufEvent ( > + IN UINTN Size > + ) > +{ > + UINT32 Event; > + > + Event = *gEventPtr++; > + if ((UINT32)(UINTN)gEventPtr >= (UINT32)(UINTN)gEventBuf + Size) { > + gEventPtr = gEventBuf; > + } > + return Event; > +} > + > +STATIC > +VOID > +DwUsb3SetFifoSize ( > + IN UINT32 Addr, > + IN UINT32 Depth, > + IN UINT32 Dir, > + IN UINT32 FifoNum > + ) > +{ > + UINT32 Reg = 0; > + > + if (Dir == FIFO_DIR_TX) { > + Reg = GTXFIFOSIZ (FifoNum); > + } else if (Dir == FIFO_DIR_RX) { > + Reg = GRXFIFOSIZ (FifoNum); > + } else { > + ASSERT (0); > + } > + MmioWrite32 (Reg, FIFOSIZ_DEP (Depth) | FIFOSIZ_ADDR (Addr)); > +} > + > +STATIC > +UINT32 > +Handshake ( What does this function do? "Handshake" does not tell me enough to figure out. > + IN UINT32 Reg, > + IN UINT32 Mask, > + IN UINT32 Done > + ) > +{ > + UINT32 Timeout = 100000; > + > + do { > + if ((MmioRead32 (Reg) & Mask) == Done) { > + return 1; > + } > + MicroSecondDelay (1); > + } while (Timeout-- > 0); > + return 0; > +} > + > +STATIC > +VOID > +DwUsb3FillDesc ( > + IN usb3_dma_desc_t *desc, > + IN UINT64 dma_addr, > + IN UINT32 dma_len, > + IN UINT32 stream, > + IN UINT32 type, > + IN UINT32 ctrlbits, > + IN UINT32 own > + ) > +{ > + desc->bptl = (UINT32)(dma_addr & 0xFFFFFFFF); > + desc->bpth = (UINT32)(dma_addr >> 32); Could you possibly create LOW_32BIT and HIGH_32BIT macros for MdePkg/Base.h instead? We are already duplicating these operations all over the place. Including all over MdeModulePkg. > + desc->status = DSCSTS_XFERCNT (dma_len); > + if (type) { > + desc->control = DSCCTL_TRBCTL (type); > + } > + desc->control |= DSCCTL_STRMID_SOFN (stream) | ctrlbits; > + ArmDataSynchronizationBarrier (); Please use MemoryFence() instead. This controller is not ARM-specific. (DSB? That sounds excessive. DMB should suffice?) > + /* must execute this operation at last */ > + if (own) { > + desc->control |= DSCCTL_HWO; > + } > + ArmDataSynchronizationBarrier (); As above. > +} > + > +STATIC > +VOID > +DwUsb3DepStartNewCfg ( > + IN UINT32 EpIdx, > + IN UINT32 RsrcIdx > + ) > +{ > + /* start the command */ > + MmioWrite32 ( > + DEPCMD (EpIdx), > + DEPCMD_XFER_RSRC_IDX (RsrcIdx) | DEPCMD_CMDTYPE (CMDTYPE_START_NEW_CFG) | \ > + DEPCMD_CMDACT > + ); > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > +} > + > +STATIC > +VOID > +DwUsb3DepCfg ( Please no abbreviations in function names. This name tells me nothing about what the function does (and there is no comment describing its function). > + IN UINT32 EpIdx, > + IN UINT32 DepCfg0, > + IN UINT32 DepCfg1, > + IN UINT32 DepCfg2 > + ) > +{ > + MmioWrite32 (DEPCMDPAR2 (EpIdx), DepCfg2); > + MmioWrite32 (DEPCMDPAR1 (EpIdx), DepCfg1); > + MmioWrite32 (DEPCMDPAR0 (EpIdx), DepCfg0); > + MmioWrite32 ( > + DEPCMD (EpIdx), > + DEPCMD_CMDTYPE (CMDTYPE_SET_EP_CFG) | DEPCMD_CMDACT > + ); > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > +} > + > +STATIC > +VOID > +DwUsb3DepXferCfg ( Dep<something>TransferConfig. Please address throughout. > + IN UINT32 EpIdx, > + IN UINT32 DepStrmCfg > + ) > +{ > + MmioWrite32 (DEPCMDPAR0 (EpIdx), DepStrmCfg); > + MmioWrite32 ( > + DEPCMD (EpIdx), > + DEPCMD_CMDTYPE (CMDTYPE_SET_XFER_CFG) | DEPCMD_CMDACT > + ); > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > +} > + > +STATIC > +UINT8 > +DwUsb3DepStartXfer ( > + IN UINT32 EpIdx, > + IN UINT64 DmaAddr, > + IN UINT32 StreamOrUf > + ) > +{ > + UINT32 Data; > + > + MmioWrite32 (DEPCMDPAR1 (EpIdx), (UINT32)DmaAddr); > + MmioWrite32 (DEPCMDPAR0 (EpIdx), (UINT32)(DmaAddr >> 32)); > + MmioWrite32 ( > + DEPCMD (EpIdx), > + DEPCMD_STR_NUM_OR_UF (StreamOrUf) | DEPCMD_CMDTYPE (CMDTYPE_START_XFER) | \ > + DEPCMD_CMDACT > + ); > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > + Data = MmioRead32 (DEPCMD (EpIdx)); > + return GET_DEPCMD_XFER_RSRC_IDX(Data); > +} > + > +STATIC > +VOID > +DwUsb3DepStopXfer ( > + IN UINT32 EpIdx, > + IN UINT32 Tri > + ) > +{ > + MmioWrite32 (DEPCMDPAR2 (EpIdx), 0); > + MmioWrite32 (DEPCMDPAR1 (EpIdx), 0); > + MmioWrite32 (DEPCMDPAR0 (EpIdx), 0); > + MmioWrite32 ( > + DEPCMD (EpIdx), > + DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_END_XFER) | \ > + DEPCMD_CMDACT > + ); > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > +} > + > +VOID > +DwUsb3DepUpdateXfer ( > + IN UINT32 EpIdx, > + IN UINT32 Tri > + ) > +{ > + MmioWrite32 ( > + DEPCMD (EpIdx), > + DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_UPDATE_XFER) | \ > + DEPCMD_CMDACT > + ); > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > +} > + > +STATIC > +VOID > +DwUsb3DepClearStall ( > + IN UINTN EpIdx > + ) > +{ > + MmioWrite32 ( > + DEPCMD (EpIdx), > + DEPCMD_CMDTYPE (CMDTYPE_CLR_STALL) | DEPCMD_CMDACT > + ); > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > +} > + > + > +STATIC > +VOID > +DwUsb3DepSetStall ( > + IN UINTN EpIdx > + ) > +{ > + MmioWrite32 ( > + DEPCMD (EpIdx), > + DEPCMD_CMDTYPE (CMDTYPE_SET_STALL) | DEPCMD_CMDACT > + ); > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > +} > + > +STATIC > +VOID > +DwUsb3EnableEp ( EnableEndpoint > + IN UINT32 EpIdx, EndpointIndex. > + IN usb3_pcd_ep_t *ep Endpoint. > + ) > +{ > + UINT32 Dalepena; What? > + > + Dalepena = MmioRead32 (DALEPENA); > + /* If the EP is already enabled, skip to set it again. */ endpoint > + if (Dalepena & (1 << EpIdx)) { > + return; > + } > + Dalepena |= 1 << EpIdx; > + MmioWrite32 (DALEPENA, Dalepena); > +} > + > +STATIC > +VOID > +DwUsb3Ep0Activate ( (EP0 is special, so may not need expanding.) > + IN OUT usb3_pcd_t *pcd > + ) > +{ > + /* issue DEPCFG command to EP0 OUT */ ... except for in comments. > + DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 0); > + DwUsb3DepCfg ( > + EP_OUT_IDX (0), > + EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512), > + EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY, > + 0 > + ); > + /* issue DEPSTRMCFG command to EP0 OUT */ > + DwUsb3DepXferCfg (EP_OUT_IDX (0), 1); // one stream > + /* issue DEPCFG command to EP0 IN */ > + DwUsb3DepCfg ( > + EP_IN_IDX (0), > + EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512) | \ > + EPCFG0_TXFNUM (pcd->ep0.tx_fifo_num), > + EPCFG1_XFER_NRDY | EPCFG1_XFER_CMPL | EPCFG1_EP_DIR_IN, > + 0 > + ); > + /* issue DEPSTRMCFG command to EP0 IN */ > + DwUsb3DepXferCfg (EP_IN_IDX (0), 1); // one stream > + pcd->ep0.active = 1; > +} > + > +STATIC > +VOID > +DwUsb3EpActivate ( > + IN OUT usb3_pcd_t *pcd, > + IN OUT usb3_pcd_ep_t *ep > + ) > +{ > + UINT32 EpIdx, DepCfg0, DepCfg1; > + if (ep->is_in) { > + EpIdx = EP_IN_IDX (ep->num); > + } else { > + EpIdx = EP_OUT_IDX (ep->num); > + } > + > + /* Start a new configurate when enable the first EP. */ > + if (!pcd->eps_enabled) { > + pcd->eps_enabled = 1; > + /* Issue DEPCFG command to physical EP1 (logical EP0 IN) first. > + * It resets the core's Tx FIFO mapping table. > + */ > + DepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL); > + DepCfg0 |= EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY); > + DepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY | EPCFG1_EP_DIR_IN; > + > + switch (pcd->speed) { > + case USB_SPEED_SUPER: > + DepCfg0 |= EPCFG0_MPS (512); > + break; > + case USB_SPEED_HIGH: > + case USB_SPEED_FULL: > + DepCfg0 |= EPCFG0_MPS (64); > + break; > + case USB_SPEED_LOW: > + DepCfg0 |= EPCFG0_MPS (8); No live coding of values. Add #defines for those speed setting values. > + break; > + default: > + ASSERT (0); > + break; > + } > + DwUsb3DepCfg (EP_IN_IDX (0), DepCfg0, DepCfg1, 0); What does that final 0 do? > + DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 2); And that 2? Please address throughout. > + } > + /* issue DEPCFG command to EP */ > + DepCfg0 = EPCFG0_EPTYPE (ep->type); > + DepCfg0 |= EPCFG0_MPS (ep->maxpacket); > + if (ep->is_in) { > + DepCfg0 |= EPCFG0_TXFNUM (ep->tx_fifo_num); > + } > + DepCfg0 |= EPCFG0_BRSTSIZ (ep->maxburst); > + DepCfg1 = EPCFG1_EP_NUM (ep->num); > + if (ep->is_in) { > + DepCfg1 |= EPCFG1_EP_DIR_IN; > + } else { > + DepCfg1 |= EPCFG1_XFER_CMPL; > + } > + DwUsb3DepCfg (EpIdx, DepCfg0, DepCfg1, 0); > + /* issue DEPSTRMCFG command to EP */ > + DwUsb3DepXferCfg (EpIdx, 1); > + DwUsb3EnableEp (EpIdx, ep); > + ep->active = 1; > +} > + > +STATIC > +VOID > +DwUsb3Ep0OutStart ( > + IN usb3_pcd_t *pcd > + ) > +{ > + usb3_dma_desc_t *desc; > + > + /* Get the SETUP packet DMA Descriptor (TRB) */ > + desc = pcd->ep0_setup_desc; > + > + /* DMA Descriptor setup */ > + DwUsb3FillDesc ( > + desc, > + (UINT64)gEndPoint0SetupPacket, > + pcd->ep0.maxpacket, > + 0, > + TRBCTL_SETUP, > + DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST, > + 1 > + ); > + > + /* issue DEPSTRTXFER command to EP0 OUT */ > + pcd->ep0.tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), (UINT64)desc, 0); > +} > + > +STATIC > +VOID > +DwUsb3Init ( > + VOID > + ) > +{ > + UINT32 Data, Addr; Address. > + usb3_pcd_t *pcd = &gPcd; > + > + /* soft reset the usb core */ > + do { > + MmioAndThenOr32 (DCTL, ~DCTL_RUN_STOP, DCTL_CSFTRST); > + > + do { > + MicroSecondDelay (1000); > + Data = MmioRead32 (DCTL); > + } while (Data & DCTL_CSFTRST); > + // > + // wait for at least 3 PHY clocks > + // > + MicroSecondDelay (1000); > + } while (0); > + > + pcd->link_state = 0; > + > + /* TI PHY: Set Turnaround Time = 9 (8-bit UTMI+ / ULPI) */ > + MmioAndThenOr32 ( > + GUSB2PHYCFG (0), > + ~GUSB2PHYCFG_USBTRDTIM_MASK, > + GUSB2PHYCFG_USBTRDTIM (9) How long is 9? I will stop my review here and give a full review on v2 when the overarching comments have been addressed. / Leif _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
On Fri, 5 Oct 2018 at 00:32, Leif Lindholm <leif.lindholm@linaro.org> wrote: > > On Mon, Aug 20, 2018 at 06:31:25PM +0800, Haojian Zhuang wrote: > > Add Designware USB 3.0 device driver. It's focus on USB device > > functionality, not USB Host functionality. The USB driver is > > mainly used for Android Fastboot application. > > > > Cc: Leif Lindholm <leif.lindholm@linaro.org> > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> > > Contributed-under: TianoCore Contribution Agreement 1.1 > > Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> > > --- > > EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec | 44 + > > EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf | 52 + > > EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h | 632 +++++ > > EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c | 2434 ++++++++++++++++++++ > > 4 files changed, 3162 insertions(+) > > > > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec > > new file mode 100644 > > index 000000000000..038e4881a948 > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec > > @@ -0,0 +1,44 @@ > > +#/** @file > > +# Framework Module Development Environment Industry Standards > > Please change this to reflect this package rather than EmbeddedPkg one > (which appears to have stolen it from an old version of MdePkg.dec :) > OK > > +# > > +# This Package provides headers and libraries that conform to EFI/PI Industry standards. > > +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> > > +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR> > > I see no need to keep these copyright statements. > OK > > +# Copyright (c) 2018, Linaro. All rights reserved.<BR> > > +# > > +# This program and the accompanying materials are licensed and made available under > > +# the terms and conditions of the BSD License which accompanies this distribution. > > +# The full text of the license may be found at > > +# http://opensource.org/licenses/bsd-license.php > > +# > > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > > +# > > +#**/ > > + > > +[Defines] > > + DEC_SPECIFICATION = 0x00010019 > > + PACKAGE_NAME = DwUsb3DxePkg > > + PACKAGE_GUID = 9b7aa6fe-405b-4955-af1f-5faf183aedec > > + PACKAGE_VERSION = 0.1 > > + > > + > > +################################################################################ > > +# > > +# Include Section - list of Include Paths that are provided by this package. > > +# Comments are used for Keywords and Module Types. > > +# > > +# Supported Module Types: > > +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION > > +# > > +################################################################################ > > + > > +[Guids.common] > > + gDwUsb3DxeTokenSpaceGuid = { 0x098a50d3, 0x92e2, 0x461a, { 0xb6, 0xba, 0xf8, 0x5d, 0x9d, 0x89, 0x49, 0xf5 }} > > + > > +[Protocols.common] > > + gDwUsbProtocolGuid = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }} > > Please make this file a common .dec for DwUsb and DwUsb3 instead of > duplicating guid information. > (If we weren't moving it to edk2-platforms, it would still have been > better to add it to EmbeddedPkg.dec.) > OK > > + > > +[PcdsFixedAtBuild.common] > > + # DwUsb Driver PCDs > > + gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress|0x0|UINT32|0x00000001 > > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf > > new file mode 100644 > > index 000000000000..510b51a34de7 > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf > > @@ -0,0 +1,52 @@ > > +#/** @file > > +# > > +# Copyright (c) 2018, Linaro Limited. All rights reserved. > > +# > > +# This program and the accompanying materials > > +# are licensed and made available under the terms and conditions of the BSD License > > +# which accompanies this distribution. The full text of the license may be found at > > +# http://opensource.org/licenses/bsd-license.php > > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > > +# > > +# > > +#**/ > > + > > +[Defines] > > + INF_VERSION = 0x00010019 > > + BASE_NAME = DwUsb3Dxe > > + FILE_GUID = 0879cd34-c399-4315-9891-56024072e711 > > + MODULE_TYPE = UEFI_DRIVER > > + VERSION_STRING = 1.0 > > + ENTRY_POINT = DwUsb3EntryPoint > > + > > +[Sources.common] > > + DwUsb3Dxe.c > > + > > +[LibraryClasses] > > + CacheMaintenanceLib > > + DebugLib > > + DmaLib > > + IoLib > > + MemoryAllocationLib > > + TimerLib > > + UefiBootServicesTableLib > > + UefiDriverEntryPoint > > + UsbSerialNumberLib > > I don't see this library anywhere in the tree? > I'll add it into the patch series for the next revision. > > + > > +[Protocols] > > + gEfiDriverBindingProtocolGuid > > + gUsbDeviceProtocolGuid > > + > > +[Packages] > > + ArmPkg/ArmPkg.dec > > + EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec > > + EmbeddedPkg/EmbeddedPkg.dec > > + MdePkg/MdePkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + > > +[Pcd] > > + gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress > > + > > +[Depex] > > + TRUE > > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h > > new file mode 100644 > > index 000000000000..92b610553169 > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h > > @@ -0,0 +1,632 @@ > > +/** @file > > + > > + Copyright (c) 2017, Linaro Limited. All rights reserved. > > + > > + This program and the accompanying materials > > + are licensed and made available under the terms and conditions of the BSD License > > + which accompanies this distribution. The full text of the license may be found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > > + > > +**/ > > + > > +#ifndef __DW_USB3_DXE_H__ > > +#define __DW_USB3_DXE_H__ > > DW -> DESIGNWARE (throughout). > OK > > + > > +#define DW_USB3_BASE FixedPcdGet32 (PcdDwUsb3DxeBaseAddress) > > + > > +#define GSBUCFG0 (DW_USB3_BASE + 0xC100) > > +#define GCTL (DW_USB3_BASE + 0xC110) > > + > > +#define GCTL_PWRDNSCALE_MASK (0x1FFF << 19) > > +#define GCTL_PWRDNSCALE(x) (((x) & 0x1FFF) << 19) > > +#define GCTL_U2RSTECN BIT16 > > +#define GCTL_PRTCAPDIR_MASK (BIT13 | BIT12) > > +#define GCTL_PRTCAPDIR_HOST BIT12 > > +#define GCTL_PRTCAPDIR_DEVICE BIT13 > > +#define GCTL_PRTCAPDIR_OTG (BIT13 | BIT12) > > +#define GCTL_U2EXIT_LFPS BIT2 > > + > > +#define GUSB2PHYCFG(x) (DW_USB3_BASE + 0xC200 + (((x) & 0xF) << 2)) > > + > > +#define GUSB2PHYCFG_USBTRDTIM_MASK (0xF << 10) > > +#define GUSB2PHYCFG_USBTRDTIM(x) (((x) & 0xF) << 10) > > +#define GUSB2PHYCFG_SUSPHY BIT6 > > + > > +#define GUSB3PIPECTL(x) (DW_USB3_BASE + 0xC2C0 + (((x) & 0x3) << 2)) > > + > > +#define PIPECTL_DELAYP1TRANS BIT18 > > +#define PIPECTL_SUSPEND_EN BIT17 > > +#define PIPECTL_LFPS_FILTER BIT9 > > +#define PIPECTL_TX_DEMPH_MASK (0x3 << 1) > > +#define PIPECTL_TX_DEMPH(x) (((x) & 0x3) << 1) > > + > > +#define GTXFIFOSIZ(x) (DW_USB3_BASE + 0xC300 + (((x) & 0x1F) << 2)) > > +#define GRXFIFOSIZ(x) (DW_USB3_BASE + 0xC380 + (((x) & 0x1F) << 2)) > > + > > +#define FIFOSIZ_ADDR(x) (((x) & 0xFFFF) << 16) > > +#define FIFOSIZ_DEP(x) ((x) & 0xFFFF) > > + > > +#define GEVNTADRL(x) (DW_USB3_BASE + 0xC400 + (((x) & 0x1F) << 2)) > > +#define GEVNTADRH(x) (DW_USB3_BASE + 0xC404 + (((x) & 0x1F) << 2)) > > +#define GEVNTSIZ(x) (DW_USB3_BASE + 0xC408 + (((x) & 0x1F) << 2)) > > + > > +#define GEVNTSIZ_EVNTINTMASK BIT31 > > +#define GEVNTSIZ_EVNTSIZ_MASK (0xFFFF) > > +#define GEVNTSIZ_EVNTSIZ(x) ((x) & 0xFFFF) > > + > > +#define GEVNTCOUNT(x) (DW_USB3_BASE + 0xC40C + (((x) & 0x1F) << 2)) > > +#define GEVNTCOUNT_EVNTCOUNT_MASK (0xFFFF) > > +#define GEVNTCOUNT_EVNTCOUNT(x) ((x) & 0xFFFF) > > + > > +// Non-Endpoint specific event flag > > +#define GEVNT_INTTYPE_MASK (0x7F << 1) > > +#define GEVNT_INTTYPE(x) (((x) & 0x7F) << 1) > > +#define EVENT_I2C_INT 4 > > +#define EVENT_CARKIT_INT 3 > > +#define EVENT_OTG_INT 1 > > +#define EVENT_DEV_INT 0 > > + > > +#define GEVNT_NON_EP BIT0 > > +// Endpoint specific event flag > > +#define GEVNT_DEPEVT_INTTYPE_MASK (0xF << 6) > > +#define GEVNT_DEPEVT_INTTYPE(x) (((x) & 0xF) << 6) > > +#define GEVNT_DEPEVT_INTTYPE_EPCMD_CMPL (7 << 6) > > +#define GEVNT_DEPEVT_INTTYPE_STRM_EVT (6 << 6) > > +#define GEVNT_DEPEVT_INTTYPE_FIFOXRUN (4 << 6) > > +#define GEVNT_DEPEVT_INTTYPE_XFER_NRDY (3 << 6) > > +#define GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG (2 << 6) > > +#define GEVNT_DEPEVT_INTTYPE_XFER_CMPL (1 << 6) > > +#define GEVNT_DEPEVT_EPNUM_MASK (0x1F << 1) > > +#define GEVNT_DEPEVT_EPNUM_SHIFT 1 > > +#define GEVNT_DEPEVT_EPNUM(x) (((x) & 0x1F) << 1) > > +// Devices specific event flag > > +#define GEVNT_DEVT_MASK (0xF << 8) > > +#define GEVNT_DEVT_SHIFT 8 > > +#define GEVNT_DEVT(x) (((x) & 0xF) << 8) > > +#define GEVNT_DEVT_INACT_TIMEOUT_RCVD (0x15 << 8) > > +#define GEVNT_DEVT_VNDR_DEV_TST_RCVD (0x14 << 8) > > +#define GEVNT_DEVT_OVERFLOW (0x13 << 8) > > +#define GEVNT_DEVT_CMD_CMPL (0x12 << 8) > > +#define GEVNT_DEVT_ERRATICERR (0x11 << 8) > > +#define GEVNT_DEVT_SOF (0x7 << 8) > > +#define GEVNT_DEVT_EOPF (0x6 << 8) > > +#define GEVNT_DEVT_HIBER_REQ (0x5 << 8) > > +#define GEVNT_DEVT_WKUP (0x4 << 8) > > +#define GEVNT_DEVT_ULST_CHNG (0x3 << 8) > > +#define GEVNT_DEVT_CONNDONE (0x2 << 8) > > +#define GEVNT_DEVT_USBRESET (0x1 << 8) > > +#define GEVNT_DEVT_DISCONN (0x0 << 8) > > + > > +#define DCFG (DW_USB3_BASE + 0xC700) > > + > > +#define DCFG_NUMP_MASK (0x1F << 17) > > +#define DCFG_NUMP(x) (((x) & 0x1F) << 17) > > +#define DCFG_DEVADDR_MASK (0x7F << 3) > > +#define DCFG_DEVADDR(x) (((x) & 0x7F) << 3) > > +#define DCFG_DEVSPD_MASK (0x7) > > +#define DCFG_DEVSPD(x) ((x) & 0x7) > > +#define DEVSPD_HS_PHY_30MHZ_OR_60MHZ 0 > > +#define DEVSPD_FS_PHY_30MHZ_OR_60MHZ 1 > > +#define DEVSPD_LS_PHY_6MHZ 2 > > +#define DEVSPD_FS_PHY_48MHZ 3 > > +#define DEVSPD_SS_PHY_125MHZ_OR_250MHZ 4 > > + > > +#define DCTL (DW_USB3_BASE + 0xC704) > > + > > +#define DCTL_RUN_STOP BIT31 > > +#define DCTL_CSFTRST BIT30 > > +#define DCTL_INIT_U2_EN BIT12 > > +#define DCTL_ACCEPT_U2_EN BIT11 > > +#define DCTL_INIT_U1_EN BIT10 > > +#define DCTL_ACCEPT_U1_EN BIT9 > > + > > +#define DEVTEN (DW_USB3_BASE + 0xC708) > > +#define DEVTEN_CONNECTDONEEN BIT2 > > +#define DEVTEN_USBRSTEN BIT1 > > +#define DEVTEN_DISCONNEN BIT0 > > + > > +#define DSTS (DW_USB3_BASE + 0xC70C) > > +#define DSTS_GET_DEVSPD(x) ((x) & 0x7) > > + > > +#define DALEPENA (DW_USB3_BASE + 0xC720) > > + > > +#define DEPCMDPAR2(x) (DW_USB3_BASE + 0xC800 + ((x) & 0x1F) * 0x10) > > +#define DEPCMDPAR1(x) (DW_USB3_BASE + 0xC804 + ((x) & 0x1F) * 0x10) > > +#define DEPCMDPAR0(x) (DW_USB3_BASE + 0xC808 + ((x) & 0x1F) * 0x10) > > +#define DEPCMD(x) (DW_USB3_BASE + 0xc80C + ((x) & 0x1F) * 0x10) > > + > > +#define DEPCMD_COMMANDPARAM_MASK (0xFFFF << 16) > > +#define DEPCMD_COMMANDPARAM(x) (((x) & 0xFFFF) << 16) > > +/* Stream Number or uFrame (input) */ > > +#define DEPCMD_STR_NUM_OR_UF_MASK (0xFFFF << 16) > > +#define DEPCMD_STR_NUM_OR_UF(x) (((x) & 0xFFFF) << 16) > > +/* Transfer Resource Index (output) */ > > +#define DEPCMD_XFER_RSRC_IDX_SHIFT 16 > > +#define DEPCMD_XFER_RSRC_IDX_MASK (0x7F << 16) > > +#define DEPCMD_XFER_RSRC_IDX(x) (((x) & 0x7F) << 16) > > +#define GET_DEPCMD_XFER_RSRC_IDX(x) (((x) >> 16) & 0x7F) > > +#define DEPCMD_CMDACT BIT10 > > +#define DEPCMD_CMDTYPE_MASK 0xFF > > +#define DEPCMD_CMDTYPE(x) ((x) & 0xFF) > > + > > +/* EP registers range as: OUT0, IN0, OUT1, IN1, ... */ > > +#define EP_OUT_IDX(x) ((x) * 2) > > +#define EP_IN_IDX(x) (((x) * 2) + 1) > > + > > +#define CMDTYPE_SET_EP_CFG 1 > > +#define CMDTYPE_SET_XFER_CFG 2 > > +#define CMDTYPE_GET_EP_STATE 3 > > +#define CMDTYPE_SET_STALL 4 > > +#define CMDTYPE_CLR_STALL 5 > > +#define CMDTYPE_START_XFER 6 > > +#define CMDTYPE_UPDATE_XFER 7 > > +#define CMDTYPE_END_XFER 8 > > +#define CMDTYPE_START_NEW_CFG 9 > > + > > +#define EPTYPE_CONTROL 0 > > +#define EPTYPE_ISOC 1 > > +#define EPTYPE_BULK 2 > > +#define EPTYPE_INTR 3 > > + > > +#define CFG_ACTION_INIT 0 > > +#define CFG_ACTION_RESTORE 1 > > +#define CFG_ACTION_MODIFY 2 > > + > > +#define EPCFG0_CFG_ACTION_MASK (0x3 << 30) > > +#define EPCFG0_CFG_ACTION(x) (((x) & 0x3) << 30) > > +#define EPCFG0_BRSTSIZ_MASK (0xF << 22) > > +#define EPCFG0_BRSTSIZ(x) (((x) & 0xF) << 22) > > +#define EPCFG0_TXFNUM_MASK (0x1F << 17) > > +#define EPCFG0_TXFNUM(x) (((x) & 0x1F) << 17) > > +#define EPCFG0_MPS_MASK (0x7FF << 3) > > +#define EPCFG0_MPS(x) (((x) & 0x7FF) << 3) > > +#define EPCFG0_EPTYPE_MASK (0x3 << 1) > > +#define EPCFG0_EPTYPE_SHIFT 1 > > +#define EPCFG0_EPTYPE(x) (((x) & 0x3) << 1) > > + > > +/* Endpoint Number */ > > +#define EPCFG1_EP_NUM_MASK (0xF << 26) > > +#define EPCFG1_EP_NUM(x) (((x) & 0xF) << 26) > > +/* Endpoint Direction */ > > +#define EPCFG1_EP_DIR_IN BIT25 > > +/* Stream Not Ready */ > > +#define EPCFG1_XFER_NRDY BIT10 > > +/* XferInProgress Enable */ > > +#define EPCFG1_XFER_IN_PROG BIT9 > > +/* Stream Completed */ > > +#define EPCFG1_XFER_CMPL BIT8 > > + > > +#define USB_SPEED_UNKNOWN 0 > > +#define USB_SPEED_LOW 1 > > +#define USB_SPEED_FULL 2 > > +#define USB_SPEED_HIGH 3 > > +#define USB_SPEED_VARIABLE 4 > > +#define USB_SPEED_SUPER 5 > > + > > +// DMA registers > > +#define DSCSTS_TRBRSP_MASK (0xF << 28) > > +#define DSCSTS_TRBRSP(x) (((x) & 0xF) << 28) > > +#define GET_DSCSTS_TRBRSP(x) (((x) >> 28) & 0xF) > > +#define TRBRSP_MISSED_ISOC_IN 1 > > +#define TRBRSP_SETUP_PEND 2 > > +#define TRBRSP_XFER_IN_PROG 4 > > +#define DSCSTS_PCM1_MASK (0x3 << 24) > > +#define DSCSTS_PCM1(x) (((x) & 0x3) << 24) > > +#define DSCSTS_XFERCNT_MASK 0xFFFFFF > > +#define DSCSTS_XFERCNT(x) ((x) & 0xFFFFFF) > > +#define GET_DSCSTS_XFERCNT(x) ((x) & 0xFFFFFF) > > + > > +#define DSCCTL_STRMID_SOFN(x) (((x) & 0xFFFF) << 14) > > +#define DSCCTL_IOC BIT11 > > +#define DSCCTL_ISP BIT10 > > +#define DSCCTL_TRBCTL_MASK (0x3F << 4) > > +#define DSCCTL_TRBCTL(x) (((x) & 0x3F) << 4) > > +#define DSCCTL_LST BIT1 > > +#define DSCCTL_HWO BIT0 > > +#define TRBCTL_NORMAL 1 > > +#define TRBCTL_SETUP 2 > > +#define TRBCTL_STATUS_2 3 > > +#define TRBCTL_STATUS_3 4 > > +#define TRBCTL_CTLDATA_1ST 5 > > +#define TRBCTL_ISOC_1ST 6 > > +#define TRBCTL_ISOC 7 > > +#define TRBCTL_LINK 8 > > +#define TRBCTL_NORMAL_ZLP 9 > > + > > + > > +#define UE_DIR_IN 0x80 > > +#define UE_DIR_OUT 0 > > +#define UE_SET_DIR(a, d) ((a) | (((d) & 1) << 7)) > > +#define UE_GET_DIR(a) ((a) & 0x80) > > +#define UE_ADDR 0x0F > > +#define UE_GET_ADDR(a) ((a) & UE_ADDR) > > + > > +#define UT_GET_DIR(a) ((a) & 0x80) > > +#define UT_WRITE 0x00 > > +#define UT_READ 0x80 > > + > > +#define UT_GET_TYPE(a) ((a) & 0x60) > > +#define UT_STANDARD 0x00 > > +#define UT_CLASS 0x20 > > +#define UT_VENDOR 0x40 > > + > > +#define UT_GET_RECIPIENT(a) ((a) & 0x1f) > > +#define UT_DEVICE 0x00 > > +#define UT_INTERFACE 0x01 > > +#define UT_ENDPOINT 0x02 > > +#define UT_OTHER 0x03 > > + > > +#define UR_GET_STATUS 0x00 > > +#define UR_CLEAR_FEATURE 0x01 > > +#define UR_SET_FEATURE 0x03 > > +#define UR_SET_ADDRESS 0x05 > > +#define UR_GET_DESCRIPTOR 0x06 > > +#define UR_SET_DESCRIPTOR 0x07 > > +#define UR_GET_CONFIG 0x08 > > +#define UR_SET_CONFIG 0x09 > > +#define UR_GET_INTERFACE 0x0A > > +#define UR_SET_INTERFACE 0x0B > > +#define UR_SYNCH_FRAME 0x0C > > +#define UR_SET_SEL 0x30 > > +#define UR_SET_ISOC_DELAY 0x31 > > + > > Somewhere around here starts a bunch of redefinitions of things > already described in MdePkg/Include/IndustryStandard/Usb.h. > Can you please reuse that include file as much as possible. > OK > > +/* Feature numbers */ > > +#define UF_ENDPOINT_HALT 0 > > +#define UF_DEVICE_REMOTE_WAKEUP 1 > > +#define UF_TEST_MODE 2 > > +#define UF_DEVICE_B_HNP_ENABLE 3 > > +#define UF_DEVICE_A_HNP_SUPPORT 4 > > +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 > > +#define UF_FUNCTION_SUSPEND 0 > > +#define UF_U1_ENABLE 48 > > +#define UF_U2_ENABLE 49 > > +#define UF_LTM_ENABLE 50 > > + > > +#define UDESC_DEVICE 0x01 > > +#define UDESC_CONFIG 0x02 > > +#define UDESC_STRING 0x03 > > +#define UDESC_INTERFACE 0x04 > > +#define UDESC_ENDPOINT 0x05 > > +#define UDESC_SS_USB_COMPANION 0x30 > > +#define UDESC_DEVICE_QUALIFIER 0x06 > > +#define UDESC_BOS 0x0f > > +#define UDESC_DEVICE_CAPABILITY 0x10 > > + > > +#define STRING_LANGUAGE 0 > > +#define STRING_MANUFACTURER 1 > > +#define STRING_PRODUCT 2 > > +#define STRING_SERIAL 3 > > + > > +#define CONFIG_VALUE 1 > > + > > +#define USB3_BULK_IN_EP 1 > > +#define USB3_BULK_OUT_EP 1 > > + > > +#define USB_ENUM_ADB_PORT_VID 0x18D1 > > +#define USB_ENUM_ADB_PORT_PID 0xD00D > > +#define USB_ENUM_INTERFACE_ADB_SUBCLASS 0x42 > > +#define USB_ENUM_INTERFACE_ADB_PROTOCOL 0x03 > > + > > +struct usb3_pcd; > > + > > +typedef enum pcd_state { > > + USB3_STATE_UNCONNECTED, /* no host */ > > + USB3_STATE_DEFAULT, > > + USB3_STATE_ADDRESSED, > > + USB3_STATE_CONFIGURED, > > +} pcdstate_e; > > These structs also break the coding style completely. > Will using IndustryStandard/Usb.h get rid of all of that? > OK > > + > > +typedef enum ep0_state { > > + EP0_IDLE, > > + EP0_IN_DATA_PHASE, > > + EP0_OUT_DATA_PHASE, > > + EP0_IN_WAIT_NRDY, > > + EP0_OUT_WAIT_NRDY, > > + EP0_IN_STATUS_PHASE, > > + EP0_OUT_STATUS_PHASE, > > + EP0_STALL, > > +} ep0state_e; > > + > > +typedef struct usb3_dma_desc { > > + /** Buffer Pointer - Low address quadlet */ > > + UINT32 bptl; > > + > > + /** Buffer Pointer - High address quadlet */ > > + UINT32 bpth; > > + > > + /** Status quadlet. Fields defined in enum @ref desc_sts_data. */ > > + UINT32 status; > > + > > + /** Control quadlet. Fields defined in enum @ref desc_ctl_data. */ > > + UINT32 control; > > +} usb3_dma_desc_t; > > + > > +typedef struct usb3_pcd_req { > > + usb3_dma_desc_t *trb; > > + UINT64 trbdma; > > + > > + UINT32 length; > > + UINT32 actual; > > + > > + UINT64 *bufdma; > > + int (*complete)(unsigned actual, int status); > > +} usb3_pcd_req_t; > > + > > +typedef struct usb_device_request { > > + UINT8 bmRequestType; > > + UINT8 bRequest; > > + UINT16 wValue; > > + UINT16 wIndex; > > + UINT16 wLength; > > +} usb_device_request_t; > > + > > +#pragma pack(1) > > +/** USB_DT_DEVICE: Device descriptor */ > > +typedef struct usb_device_descriptor { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + > > + UINT16 bcdUSB; > > +#define USB_CLASS_COMM 0x02 > > +#define USB_CLASS_VENDOR_SPEC 0xFF > > +#define USB_SC_VENDOR_SPEC 0xFF > > +#define USB_PR_VENDOR_SPEC 0xFF > > + UINT8 bDeviceClass; > > + UINT8 bDeviceSubClass; > > + UINT8 bDeviceProtocol; > > + UINT8 bMaxPacketSize0; > > + UINT16 idVendor; > > + UINT16 idProduct; > > + UINT16 bcdDevice; > > + UINT8 iManufacturer; > > + UINT8 iProduct; > > + UINT8 iSerialNumber; > > + UINT8 bNumConfigurations; > > +} usb_device_descriptor_t; > > + > > +/* USB_DT_CONFIG: Config descriptor */ > > +typedef struct usb_config_descriptor { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + > > + UINT16 wTotalLength; > > + UINT8 bNumInterfaces; > > +#define CONFIG_VALUE 1 > > + UINT8 bConfigurationValue; > > + UINT8 iConfiguration; > > +#define USB_CONFIG_ATT_ONE (1 << 7) > > + UINT8 bmAttributes; > > +#define USB_CONFIG_VBUS_DRAW (0xFA) > > + UINT8 bMaxPower; > > +} usb_config_descriptor_t; > > + > > +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ > > +typedef struct usb_qualifier_descriptor { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + > > + UINT16 bcdUSB; > > + UINT8 bDeviceClass; > > + UINT8 bDeviceSubClass; > > + UINT8 bDeviceProtocol; > > + UINT8 bMaxPacketSize0; > > + UINT8 bNumConfigurations; > > + UINT8 bRESERVED; > > +} usb_qualifier_descriptor_t; > > + > > +/* USB_DT_INTERFACE: Interface descriptor */ > > +typedef struct usb_interface_descriptor { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + > > + UINT8 bInterfaceNumber; > > + UINT8 bAlternateSetting; > > + UINT8 bNumEndpoints; > > + UINT8 bInterfaceClass; > > + UINT8 bInterfaceSubClass; > > + UINT8 bInterfaceProtocol; > > + UINT8 iInterface; > > +} usb_interface_descriptor_t; > > + > > +/* USB_DT_ENDPOINT: Endpoint descriptor */ > > +typedef struct usb_endpoint_descriptor { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + > > + UINT8 bEndpointAddress; > > + UINT8 bmAttributes; > > +#define USB_ENDPOINT_XFER_CONTROL 0x00 > > +#define USB_ENDPOINT_XFER_ISOC 0x01 > > +#define USB_ENDPOINT_XFER_BULK 0x02 > > +#define USB_ENDPOINT_XFER_INT 0x03 > > + UINT16 wMaxPacketSize; > > + UINT8 bInterval; > > +} usb_endpoint_descriptor_t; > > + > > +/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ > > +typedef struct usb_ss_ep_comp_descriptor { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + > > + UINT8 bMaxBurst; > > + UINT8 bmAttributes; > > + UINT16 wBytesPerInterval; > > +} usb_ss_ep_comp_descriptor_t; > > + > > +/* WUSB BOS Descriptor (Binary device Object Store) */ > > +typedef struct wusb_bos_desc { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + UINT16 wTotalLength; > > + UINT8 bNumDeviceCaps; > > +} wusb_bos_desc_t; > > + > > +#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 > > +typedef struct usb_dev_cap_20_ext_desc { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + UINT8 bDevCapabilityType; > > +#define USB_20_EXT_LPM 0x02 > > + UINT32 bmAttributes; > > +} usb_dev_cap_20_ext_desc_t; > > + > > +#define USB_DEVICE_CAPABILITY_SS_USB 0x03 > > +typedef struct usb_dev_cap_ss_usb { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + UINT8 bDevCapabilityType; > > +#define USB_DC_SS_USB_LTM_CAPABLE 0x02 > > + UINT8 bmAttributes; > > +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 > > +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 > > +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 > > +#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 > > + UINT32 wSpeedsSupported; > > + UINT8 bFunctionalitySupport; > > + UINT8 bU1DevExitLat; > > + UINT32 wU2DevExitLat; > > +} usb_dev_cap_ss_usb_t; > > + > > +#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 > > +typedef struct usb_dev_cap_container_id { > > + UINT8 bLength; > > + UINT8 bDescriptorType; > > + UINT8 bDevCapabilityType; > > + UINT8 bReserved; > > + UINT8 containerID[16]; > > +} usb_dev_cap_container_id_t; > > +#pragma pack() > > + > > +typedef union usb_setup_pkt { > > + usb_device_request_t req; > > + UINT32 d32[2]; > > + UINT8 d8[8]; > > +} usb_setup_pkt_t; > > + > > +typedef struct usb3_pcd_ep { > > + struct usb3_pcd *pcd; > > + > > + UINT8 EpInIdx; > > + UINT8 EpOutIdx; > > + UINT8 phys; > > + > > + //UINT8 phys; > > + UINT8 num; > > + UINT8 type; > > + UINT8 maxburst; > > + UINT16 maxpacket; > > + /* Tx FIFO # for IN EPs */ > > + UINT8 tx_fifo_num; > > + > > + /* The Transfer Resource Index from the Start Transfer command */ > > + UINT8 tri_out; > > + UINT8 tri_in; > > + > > + UINT8 stopped; > > + /* Send ZLP */ > > + UINT8 send_zlp; > > + /* True if 3-stage control transfer */ > > + UINT8 three_stage; > > + /* True if transfer has been started on EP */ > > + UINT8 xfer_started; > > + /* EP direction 0 = OUT */ > > + UINT8 is_in; > > + /* True if endpoint is active */ > > + UINT8 active; > > + /* Initial data pid of bulk endpoint */ > > + UINT8 data_pid_start; > > + > > + /* ep_desc (excluding ep0) */ > > + usb3_dma_desc_t *ep_desc; > > + > > +#if 0 > > + /* TRB descriptor must be aligned to 16 bytes */ > > + UINT8 epx_desc[32]; > > +#endif > > + > > + /* request (excluding ep0) */ > > + usb3_pcd_req_t req; > > +} usb3_pcd_ep_t; > > + > > +typedef struct usb3_pcd { > > + //struct usb3_device *usb3_dev; > > + > > + INT32 link_state; > > + pcdstate_e state; > > + UINT8 new_config; > > + ep0state_e ep0state; > > + > > + UINT32 eps_enabled; > > + UINT32 ltm_enable; > > + > > + usb3_pcd_ep_t ep0; > > + usb3_pcd_ep_t out_ep; > > + usb3_pcd_ep_t in_ep; > > + > > + /* > > + usb3_dev_global_regs_t *dev_global_regs; > > + usb3_dev_ep_regs_t *out_ep_regs; > > + usb3_dev_ep_regs_t *in_ep_regs; > > + */ > > + > > + usb3_pcd_req_t ep0_req; > > + > > + UINT8 speed; > > + > > + usb3_dma_desc_t *ep0_setup_desc; > > + usb3_dma_desc_t *ep0_in_desc; > > + usb3_dma_desc_t *ep0_out_desc; > > + > > + /* TRB descriptor must be aligned to 16 bytes */ > > +#if 0 > > + UINT8 ep0_setup[32]; > > + UINT8 ep0_in[32]; > > + UINT8 ep0_out[32]; > > + > > + usb_setup_pkt_t ep0_setup_pkt[5]; > > + > > +#define USB3_STATUS_BUF_SIZE 512 > > + UINT8 ep0_status_buf[USB3_STATUS_BUF_SIZE]; > > + > > +#define USB3_BULK_BUF_SIZE 2048 > > + UINT8 ss_bulk_buf[USB3_BULK_BUF_SIZE]; > > +#endif > > + > > + UINT32 file_type; > > + UINT32 file_address; > > + UINT32 file_capacity; > > + UINT32 file_total_frame; > > + UINT32 file_curr_frame; > > + UINT32 file_next_frame; > > + UINT32 file_received; > > + UINT32 file_complete; > > + > > + UINT16 test_mode_nr; > > + UINT16 test_mode; > > +} usb3_pcd_t; > > + > > +struct usb_enum_port_param { > > + UINT16 idVendor; > > + UINT16 idProduct; > > + UINT8 bInterfaceSubClass; > > + UINT8 bInterfaceProtocol; > > +}; > > + > > +#if 0 > > If not used, leave it out. > OK > > +typedef struct usb3_pcd_req { > > + usb3_dma_desc_t *trb; > > + UINT64 trbdma; > > + > > + UINT32 length; > > + UINT32 actual; > > + > > + UINT64 *bufdma; > > + int (*complete)(unsigned actual, int status); > > +} usb3_pcd_req_t; > > + > > +#endif > > + > > +#endif /* __DW_USB3_DXE_H__ */ > > diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c > > new file mode 100644 > > index 000000000000..83d5e4736de0 > > --- /dev/null > > +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c > > @@ -0,0 +1,2434 @@ > > +/** @file > > + > > + Copyright (c) 2018, Linaro Limited. All rights reserved. > > + > > + This program and the accompanying materials are licensed and made available > > + under the terms and conditions of the BSD License which accompanies this > > + distribution. The full text of the license may be found at > > + http://opensource.org/licenses/bsd-license.php > > + > > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > > + > > +**/ > > + > > +#include <IndustryStandard/Usb.h> > > +#include <Library/ArmLib.h> > > +#include <Library/BaseLib.h> > > +#include <Library/BaseMemoryLib.h> > > +#include <Library/CacheMaintenanceLib.h> > > +#include <Library/DebugLib.h> > > +#include <Library/DmaLib.h> > > +#include <Library/IoLib.h> > > +#include <Library/MemoryAllocationLib.h> > > +#include <Library/TimerLib.h> > > +#include <Library/UefiBootServicesTableLib.h> > > +#include <Library/UefiDriverEntryPoint.h> > > +#include <Library/UefiRuntimeServicesTableLib.h> > > +#include <Protocol/DwUsb.h> > > +#include <Protocol/DriverBinding.h> > > +#include <Protocol/UsbDevice.h> > > + > > +#include "DwUsb3Dxe.h" > > + > > +#define FIFO_DIR_TX 0 > > +#define FIFO_DIR_RX 1 > > + > > +#define TX_FIFO_ADDR 0 > > +#define RX_FIFO_ADDR 0 > > + > > +#define RAM_WIDTH 8 > > +#define RAM_TX0_DEPTH 2048 > > +#define RAM_TX1_DEPTH 4096 > > +#define RAM_RX_DEPTH 8192 > > Should these not also go into DwUsb3Dxe.h? > OK > > + > > +#define USB_TYPE_LENGTH 16 > > +#define USB_BLOCK_HIGH_SPEED_SIZE 512 > > +#define DATA_SIZE 131072 > > +#define CMD_SIZE 512 > > What do the above definitions mean? > I'll add comment. > > +#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1) > > This one does not appear to be used? > OK > > + > > +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) > > Use available macros in Base.h. > OK > > + > > +// > > +// The time between interrupt polls, in units of 100 nanoseconds > > +// 10 Microseconds > > +// > > +#define DW_INTERRUPT_POLL_PERIOD 100 > > + > > +#define DWUSB3_EVENT_BUF_SIZE 256 > > + > > +// > > +// Maxpacket size for EP0, defined by USB3 spec > > +// > > +#define USB3_MAX_EP0_SIZE 512 > > + > > +// > > +// Maxpacket size for any EP, defined by USB3 spec > > +// > > +#define USB3_MAX_PACKET_SIZE 1024 > > +#define USB2_HS_MAX_PACKET_SIZE 512 > > +#define USB2_FS_MAX_PACKET_SIZE 64 > > + > > +#define USB3_STATE_UNCONNECTED 0 > > +#define USB3_STATE_DEFAULT 1 > > +#define USB3_STATE_ADDRESSED 2 > > +#define USB3_STATE_CONFIGURED 3 > > + > > +#define USB3_STATUS_BUF_SIZE 512 > > If these are defined by USB3 spec, please add them to > MdePkg/Include/IndustryStandard/Usb.h instead of defining them > locally. > OK > > + > > +#define GET_EVENTBUF_COUNT() \ > > + (GEVNTCOUNT_EVNTCOUNT (MmioRead32 (GEVNTCOUNT (0)))) > > +#define UPDATE_EVENTBUF_COUNT(x) \ > > + (MmioWrite32 (GEVNTCOUNT (0), GEVNTCOUNT_EVNTCOUNT (x))) > > + > > +#define SET_DEVADDR(x) \ > > + (MmioAndThenOr32 (DCFG, ~DCFG_DEVADDR_MASK, DCFG_DEVADDR (x))) > > Should these not also move to DwUsb3Dxe.h? > OK > > + > > +EFI_GUID gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID; > > This looks less than ideal - this makes it impossible to include > DwUsb2 and DwUsb3 drivers in the same image. > On the view of hardware, DwUsb2 and DwUsb3 doesn't exist at the same time. > > + > > +STATIC DW_USB_PROTOCOL *DwUsb; > > + > > +STATIC usb3_pcd_t gPcd; > > This seems a very unfortunate choice for variable name. > OK. I'll rename it. > > +STATIC UINT32 *gEventBuf, *gEventPtr; > > +STATIC struct usb_device_descriptor gDwUsb3DevDesc; > > +STATIC VOID *gRxBuf; > > + > > +STATIC usb_setup_pkt_t *gEndPoint0SetupPacket; > > +STATIC UINT8 *gEndPoint0StatusBuf; > > Although most if not all of these will disappear when converting to > UEFI driver model, why do they have 'g' prefix in the first place? > 'g' is for globally visible symbols. Variables that are "global" in > this file only are better off using 'm'. OK. I'll fix it. > > > +STATIC USB_DEVICE_RX_CALLBACK mDataReceivedCallback; > > +STATIC UINTN mDataBufferSize; > > + > > +struct usb_interface_descriptor intf = { > > + sizeof (struct usb_interface_descriptor), > > + UDESC_INTERFACE, > > + 0, > > + 0, > > + 2, > > + USB_CLASS_VENDOR_SPEC, > > + 0x42, > > + 0x03, > > + 0 > > +}; > > + > > +const struct usb_ss_ep_comp_descriptor ep_comp = { > > + sizeof (struct usb_ss_ep_comp_descriptor), > > + UDESC_SS_USB_COMPANION, > > + 0, > > + 0, > > + 0 > > +}; > > + > > +const struct usb_endpoint_descriptor hs_bulk_in = { > > + sizeof (struct usb_endpoint_descriptor), > > + UDESC_ENDPOINT, > > + UE_DIR_IN | USB3_BULK_IN_EP, > > + USB_ENDPOINT_XFER_BULK, > > + 0x200, > > + 0 > > +}; > > + > > +const struct usb_endpoint_descriptor > > +hs_bulk_out = { > > + sizeof(struct usb_endpoint_descriptor), /* bLength */ > > + UDESC_ENDPOINT, /* bDescriptorType */ > > + > > + UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */ > > + USB_ENDPOINT_XFER_BULK, /* bmAttributes */ > > + 0x200, /* wMaxPacketSize: 512 of high-speed */ > > + 1, /* bInterval */ > > +}; > > + > > +const struct usb_endpoint_descriptor ss_bulk_in = { > > + sizeof(struct usb_endpoint_descriptor), /* bLength */ > > + UDESC_ENDPOINT, /* bDescriptorType */ > > + > > + UE_DIR_IN | USB3_BULK_IN_EP, /* bEndpointAddress */ > > + USB_ENDPOINT_XFER_BULK, /* bmAttributes */ > > + 0x400, /* wMaxPacketSize: 1024 of super-speed */ > > + 0, /* bInterval */ > > +}; > > + > > +const struct usb_endpoint_descriptor ss_bulk_out = { > > + sizeof(struct usb_endpoint_descriptor), /* bLength */ > > + UDESC_ENDPOINT, /* bDescriptorType */ > > + > > + UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */ > > + USB_ENDPOINT_XFER_BULK, /* bmAttributes */ > > + 0x400, /* wMaxPacketSize: 1024 of super-speed */ > > + 0, /* bInterval */ > > +}; > > + > > +/** The BOS Descriptor */ > > What's a BOS? > Let me add comment on it. > > + > > +const struct usb_dev_cap_20_ext_desc cap1 = { > > + sizeof(struct usb_dev_cap_20_ext_desc), /* bLength */ > > + UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ > > + USB_DEVICE_CAPABILITY_20_EXTENSION, /* bDevCapabilityType */ > > + 0x2, /* bmAttributes */ > > +}; > > + > > +const struct usb_dev_cap_ss_usb > > +cap2 = { > > + sizeof(struct usb_dev_cap_ss_usb), /* bLength */ > > + UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ > > + USB_DEVICE_CAPABILITY_SS_USB, /* bDevCapabilityType */ > > + 0x0, /* bmAttributes */ > > + (USB_DC_SS_USB_SPEED_SUPPORT_SS | > > + USB_DC_SS_USB_SPEED_SUPPORT_HIGH), /* wSpeedsSupported */ > > + 0x2, /* bFunctionalitySupport */ > > + 0xa, /* bU1DevExitLat */ > > + 0x100, /* wU2DevExitLat */ > > +}; > > + > > +const struct usb_dev_cap_container_id > > +cap3 = { > > + sizeof(struct usb_dev_cap_container_id),/* bLength */ > > + UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ > > + USB_DEVICE_CAPABILITY_CONTAINER_ID, /* bDevCapabilityType */ > > + 0, /* bReserved */ > > + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* containerID */ > > +}; > > + > > +const struct wusb_bos_desc > > +bos = { > > + sizeof(struct wusb_bos_desc), /* bLength */ > > + UDESC_BOS, /* bDescriptorType */ > > + (sizeof(struct wusb_bos_desc) + \ > > + sizeof(cap1) + sizeof(cap2) + \ > > + sizeof(cap3)), /* wTotalLength */ > > + 3, /* bNumDeviceCaps */ > > +}; > > + > > +STATIC struct usb_enum_port_param usb_port_activity_config = { > > + .idVendor = USB_ENUM_ADB_PORT_VID, > > + .idProduct = USB_ENUM_ADB_PORT_PID, > > + .bInterfaceSubClass = USB_ENUM_INTERFACE_ADB_SUBCLASS, > > + .bInterfaceProtocol = USB_ENUM_INTERFACE_ADB_PROTOCOL > > +}; > > + > > +STATIC > > +UINT32 > > +DwUsb3GetEventBufEvent ( > > + IN UINTN Size > > + ) > > +{ > > + UINT32 Event; > > + > > + Event = *gEventPtr++; > > + if ((UINT32)(UINTN)gEventPtr >= (UINT32)(UINTN)gEventBuf + Size) { > > + gEventPtr = gEventBuf; > > + } > > + return Event; > > +} > > + > > +STATIC > > +VOID > > +DwUsb3SetFifoSize ( > > + IN UINT32 Addr, > > + IN UINT32 Depth, > > + IN UINT32 Dir, > > + IN UINT32 FifoNum > > + ) > > +{ > > + UINT32 Reg = 0; > > + > > + if (Dir == FIFO_DIR_TX) { > > + Reg = GTXFIFOSIZ (FifoNum); > > + } else if (Dir == FIFO_DIR_RX) { > > + Reg = GRXFIFOSIZ (FifoNum); > > + } else { > > + ASSERT (0); > > + } > > + MmioWrite32 (Reg, FIFOSIZ_DEP (Depth) | FIFOSIZ_ADDR (Addr)); > > +} > > + > > +STATIC > > +UINT32 > > +Handshake ( > > What does this function do? "Handshake" does not tell me enough to > figure out. > > > + IN UINT32 Reg, > > + IN UINT32 Mask, > > + IN UINT32 Done > > + ) > > +{ > > + UINT32 Timeout = 100000; > > + > > + do { > > + if ((MmioRead32 (Reg) & Mask) == Done) { > > + return 1; > > + } > > + MicroSecondDelay (1); > > + } while (Timeout-- > 0); > > + return 0; > > +} > > + > > +STATIC > > +VOID > > +DwUsb3FillDesc ( > > + IN usb3_dma_desc_t *desc, > > + IN UINT64 dma_addr, > > + IN UINT32 dma_len, > > + IN UINT32 stream, > > + IN UINT32 type, > > + IN UINT32 ctrlbits, > > + IN UINT32 own > > + ) > > +{ > > + desc->bptl = (UINT32)(dma_addr & 0xFFFFFFFF); > > + desc->bpth = (UINT32)(dma_addr >> 32); > > Could you possibly create LOW_32BIT and HIGH_32BIT macros for > MdePkg/Base.h instead? We are already duplicating these operations all > over the place. Including all over MdeModulePkg. > OK > > + desc->status = DSCSTS_XFERCNT (dma_len); > > + if (type) { > > + desc->control = DSCCTL_TRBCTL (type); > > + } > > + desc->control |= DSCCTL_STRMID_SOFN (stream) | ctrlbits; > > + ArmDataSynchronizationBarrier (); > > Please use MemoryFence() instead. > This controller is not ARM-specific. > > (DSB? That sounds excessive. DMB should suffice?) > OK > > + /* must execute this operation at last */ > > + if (own) { > > + desc->control |= DSCCTL_HWO; > > + } > > + ArmDataSynchronizationBarrier (); > > As above. > OK > > +} > > + > > +STATIC > > +VOID > > +DwUsb3DepStartNewCfg ( > > + IN UINT32 EpIdx, > > + IN UINT32 RsrcIdx > > + ) > > +{ > > + /* start the command */ > > + MmioWrite32 ( > > + DEPCMD (EpIdx), > > + DEPCMD_XFER_RSRC_IDX (RsrcIdx) | DEPCMD_CMDTYPE (CMDTYPE_START_NEW_CFG) | \ > > + DEPCMD_CMDACT > > + ); > > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > > +} > > + > > +STATIC > > +VOID > > +DwUsb3DepCfg ( > > Please no abbreviations in function names. This name tells me nothing > about what the function does (and there is no comment describing its > function). > OK > > + IN UINT32 EpIdx, > > + IN UINT32 DepCfg0, > > + IN UINT32 DepCfg1, > > + IN UINT32 DepCfg2 > > + ) > > +{ > > + MmioWrite32 (DEPCMDPAR2 (EpIdx), DepCfg2); > > + MmioWrite32 (DEPCMDPAR1 (EpIdx), DepCfg1); > > + MmioWrite32 (DEPCMDPAR0 (EpIdx), DepCfg0); > > + MmioWrite32 ( > > + DEPCMD (EpIdx), > > + DEPCMD_CMDTYPE (CMDTYPE_SET_EP_CFG) | DEPCMD_CMDACT > > + ); > > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > > +} > > + > > +STATIC > > +VOID > > +DwUsb3DepXferCfg ( > > Dep<something>TransferConfig. > Please address throughout. > > > + IN UINT32 EpIdx, > > + IN UINT32 DepStrmCfg > > + ) > > +{ > > + MmioWrite32 (DEPCMDPAR0 (EpIdx), DepStrmCfg); > > + MmioWrite32 ( > > + DEPCMD (EpIdx), > > + DEPCMD_CMDTYPE (CMDTYPE_SET_XFER_CFG) | DEPCMD_CMDACT > > + ); > > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > > +} > > + > > +STATIC > > +UINT8 > > +DwUsb3DepStartXfer ( > > + IN UINT32 EpIdx, > > + IN UINT64 DmaAddr, > > + IN UINT32 StreamOrUf > > + ) > > +{ > > + UINT32 Data; > > + > > + MmioWrite32 (DEPCMDPAR1 (EpIdx), (UINT32)DmaAddr); > > + MmioWrite32 (DEPCMDPAR0 (EpIdx), (UINT32)(DmaAddr >> 32)); > > + MmioWrite32 ( > > + DEPCMD (EpIdx), > > + DEPCMD_STR_NUM_OR_UF (StreamOrUf) | DEPCMD_CMDTYPE (CMDTYPE_START_XFER) | \ > > + DEPCMD_CMDACT > > + ); > > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > > + Data = MmioRead32 (DEPCMD (EpIdx)); > > + return GET_DEPCMD_XFER_RSRC_IDX(Data); > > +} > > + > > +STATIC > > +VOID > > +DwUsb3DepStopXfer ( > > + IN UINT32 EpIdx, > > + IN UINT32 Tri > > + ) > > +{ > > + MmioWrite32 (DEPCMDPAR2 (EpIdx), 0); > > + MmioWrite32 (DEPCMDPAR1 (EpIdx), 0); > > + MmioWrite32 (DEPCMDPAR0 (EpIdx), 0); > > + MmioWrite32 ( > > + DEPCMD (EpIdx), > > + DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_END_XFER) | \ > > + DEPCMD_CMDACT > > + ); > > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > > +} > > + > > +VOID > > +DwUsb3DepUpdateXfer ( > > + IN UINT32 EpIdx, > > + IN UINT32 Tri > > + ) > > +{ > > + MmioWrite32 ( > > + DEPCMD (EpIdx), > > + DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_UPDATE_XFER) | \ > > + DEPCMD_CMDACT > > + ); > > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > > +} > > + > > +STATIC > > +VOID > > +DwUsb3DepClearStall ( > > + IN UINTN EpIdx > > + ) > > +{ > > + MmioWrite32 ( > > + DEPCMD (EpIdx), > > + DEPCMD_CMDTYPE (CMDTYPE_CLR_STALL) | DEPCMD_CMDACT > > + ); > > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > > +} > > + > > + > > +STATIC > > +VOID > > +DwUsb3DepSetStall ( > > + IN UINTN EpIdx > > + ) > > +{ > > + MmioWrite32 ( > > + DEPCMD (EpIdx), > > + DEPCMD_CMDTYPE (CMDTYPE_SET_STALL) | DEPCMD_CMDACT > > + ); > > + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); > > +} > > + > > +STATIC > > +VOID > > +DwUsb3EnableEp ( > > EnableEndpoint > OK > > + IN UINT32 EpIdx, > > EndpointIndex. > OK > > + IN usb3_pcd_ep_t *ep > > Endpoint. > OK > > + ) > > +{ > > + UINT32 Dalepena; > > What? > > > + > > + Dalepena = MmioRead32 (DALEPENA); > > + /* If the EP is already enabled, skip to set it again. */ > > endpoint > > > + if (Dalepena & (1 << EpIdx)) { > > + return; > > + } > > + Dalepena |= 1 << EpIdx; > > + MmioWrite32 (DALEPENA, Dalepena); > > +} > > + > > +STATIC > > +VOID > > +DwUsb3Ep0Activate ( > > (EP0 is special, so may not need expanding.) > > > + IN OUT usb3_pcd_t *pcd > > + ) > > +{ > > + /* issue DEPCFG command to EP0 OUT */ > > ... except for in comments. > > > + DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 0); > > + DwUsb3DepCfg ( > > + EP_OUT_IDX (0), > > + EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512), > > + EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY, > > + 0 > > + ); > > + /* issue DEPSTRMCFG command to EP0 OUT */ > > + DwUsb3DepXferCfg (EP_OUT_IDX (0), 1); // one stream > > + /* issue DEPCFG command to EP0 IN */ > > + DwUsb3DepCfg ( > > + EP_IN_IDX (0), > > + EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512) | \ > > + EPCFG0_TXFNUM (pcd->ep0.tx_fifo_num), > > + EPCFG1_XFER_NRDY | EPCFG1_XFER_CMPL | EPCFG1_EP_DIR_IN, > > + 0 > > + ); > > + /* issue DEPSTRMCFG command to EP0 IN */ > > + DwUsb3DepXferCfg (EP_IN_IDX (0), 1); // one stream > > + pcd->ep0.active = 1; > > +} > > + > > +STATIC > > +VOID > > +DwUsb3EpActivate ( > > + IN OUT usb3_pcd_t *pcd, > > + IN OUT usb3_pcd_ep_t *ep > > + ) > > +{ > > + UINT32 EpIdx, DepCfg0, DepCfg1; > > + if (ep->is_in) { > > + EpIdx = EP_IN_IDX (ep->num); > > + } else { > > + EpIdx = EP_OUT_IDX (ep->num); > > + } > > + > > + /* Start a new configurate when enable the first EP. */ > > + if (!pcd->eps_enabled) { > > + pcd->eps_enabled = 1; > > + /* Issue DEPCFG command to physical EP1 (logical EP0 IN) first. > > + * It resets the core's Tx FIFO mapping table. > > + */ > > + DepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL); > > + DepCfg0 |= EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY); > > + DepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY | EPCFG1_EP_DIR_IN; > > + > > + switch (pcd->speed) { > > + case USB_SPEED_SUPER: > > + DepCfg0 |= EPCFG0_MPS (512); > > + break; > > + case USB_SPEED_HIGH: > > + case USB_SPEED_FULL: > > + DepCfg0 |= EPCFG0_MPS (64); > > + break; > > + case USB_SPEED_LOW: > > + DepCfg0 |= EPCFG0_MPS (8); > > No live coding of values. > Add #defines for those speed setting values. > > > + break; > > + default: > > + ASSERT (0); > > + break; > > + } > > + DwUsb3DepCfg (EP_IN_IDX (0), DepCfg0, DepCfg1, 0); > > What does that final 0 do? > > > + DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 2); > > And that 2? > > Please address throughout. > > > + } > > + /* issue DEPCFG command to EP */ > > + DepCfg0 = EPCFG0_EPTYPE (ep->type); > > + DepCfg0 |= EPCFG0_MPS (ep->maxpacket); > > + if (ep->is_in) { > > + DepCfg0 |= EPCFG0_TXFNUM (ep->tx_fifo_num); > > + } > > + DepCfg0 |= EPCFG0_BRSTSIZ (ep->maxburst); > > + DepCfg1 = EPCFG1_EP_NUM (ep->num); > > + if (ep->is_in) { > > + DepCfg1 |= EPCFG1_EP_DIR_IN; > > + } else { > > + DepCfg1 |= EPCFG1_XFER_CMPL; > > + } > > + DwUsb3DepCfg (EpIdx, DepCfg0, DepCfg1, 0); > > + /* issue DEPSTRMCFG command to EP */ > > + DwUsb3DepXferCfg (EpIdx, 1); > > + DwUsb3EnableEp (EpIdx, ep); > > + ep->active = 1; > > +} > > + > > +STATIC > > +VOID > > +DwUsb3Ep0OutStart ( > > + IN usb3_pcd_t *pcd > > + ) > > +{ > > + usb3_dma_desc_t *desc; > > + > > + /* Get the SETUP packet DMA Descriptor (TRB) */ > > + desc = pcd->ep0_setup_desc; > > + > > + /* DMA Descriptor setup */ > > + DwUsb3FillDesc ( > > + desc, > > + (UINT64)gEndPoint0SetupPacket, > > + pcd->ep0.maxpacket, > > + 0, > > + TRBCTL_SETUP, > > + DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST, > > + 1 > > + ); > > + > > + /* issue DEPSTRTXFER command to EP0 OUT */ > > + pcd->ep0.tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), (UINT64)desc, 0); > > +} > > + > > +STATIC > > +VOID > > +DwUsb3Init ( > > + VOID > > + ) > > +{ > > + UINT32 Data, Addr; > > Address. > > > + usb3_pcd_t *pcd = &gPcd; > > + > > + /* soft reset the usb core */ > > + do { > > + MmioAndThenOr32 (DCTL, ~DCTL_RUN_STOP, DCTL_CSFTRST); > > + > > + do { > > + MicroSecondDelay (1000); > > + Data = MmioRead32 (DCTL); > > + } while (Data & DCTL_CSFTRST); > > + // > > + // wait for at least 3 PHY clocks > > + // > > + MicroSecondDelay (1000); > > + } while (0); > > + > > + pcd->link_state = 0; > > + > > + /* TI PHY: Set Turnaround Time = 9 (8-bit UTMI+ / ULPI) */ > > + MmioAndThenOr32 ( > > + GUSB2PHYCFG (0), > > + ~GUSB2PHYCFG_USBTRDTIM_MASK, > > + GUSB2PHYCFG_USBTRDTIM (9) > > How long is 9? > > I will stop my review here and give a full review on v2 when the > overarching comments have been addressed. > OK Best Regards Haojian _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec new file mode 100644 index 000000000000..038e4881a948 --- /dev/null +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec @@ -0,0 +1,44 @@ +#/** @file +# Framework Module Development Environment Industry Standards +# +# This Package provides headers and libraries that conform to EFI/PI Industry standards. +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR> +# Copyright (c) 2018, Linaro. All rights reserved.<BR> +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + DEC_SPECIFICATION = 0x00010019 + PACKAGE_NAME = DwUsb3DxePkg + PACKAGE_GUID = 9b7aa6fe-405b-4955-af1f-5faf183aedec + PACKAGE_VERSION = 0.1 + + +################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################ + +[Guids.common] + gDwUsb3DxeTokenSpaceGuid = { 0x098a50d3, 0x92e2, 0x461a, { 0xb6, 0xba, 0xf8, 0x5d, 0x9d, 0x89, 0x49, 0xf5 }} + +[Protocols.common] + gDwUsbProtocolGuid = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }} + +[PcdsFixedAtBuild.common] + # DwUsb Driver PCDs + gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress|0x0|UINT32|0x00000001 diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf new file mode 100644 index 000000000000..510b51a34de7 --- /dev/null +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf @@ -0,0 +1,52 @@ +#/** @file +# +# Copyright (c) 2018, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = DwUsb3Dxe + FILE_GUID = 0879cd34-c399-4315-9891-56024072e711 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DwUsb3EntryPoint + +[Sources.common] + DwUsb3Dxe.c + +[LibraryClasses] + CacheMaintenanceLib + DebugLib + DmaLib + IoLib + MemoryAllocationLib + TimerLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UsbSerialNumberLib + +[Protocols] + gEfiDriverBindingProtocolGuid + gUsbDeviceProtocolGuid + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[Pcd] + gDwUsb3DxeTokenSpaceGuid.PcdDwUsb3DxeBaseAddress + +[Depex] + TRUE diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h new file mode 100644 index 000000000000..92b610553169 --- /dev/null +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h @@ -0,0 +1,632 @@ +/** @file + + Copyright (c) 2017, Linaro Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DW_USB3_DXE_H__ +#define __DW_USB3_DXE_H__ + +#define DW_USB3_BASE FixedPcdGet32 (PcdDwUsb3DxeBaseAddress) + +#define GSBUCFG0 (DW_USB3_BASE + 0xC100) +#define GCTL (DW_USB3_BASE + 0xC110) + +#define GCTL_PWRDNSCALE_MASK (0x1FFF << 19) +#define GCTL_PWRDNSCALE(x) (((x) & 0x1FFF) << 19) +#define GCTL_U2RSTECN BIT16 +#define GCTL_PRTCAPDIR_MASK (BIT13 | BIT12) +#define GCTL_PRTCAPDIR_HOST BIT12 +#define GCTL_PRTCAPDIR_DEVICE BIT13 +#define GCTL_PRTCAPDIR_OTG (BIT13 | BIT12) +#define GCTL_U2EXIT_LFPS BIT2 + +#define GUSB2PHYCFG(x) (DW_USB3_BASE + 0xC200 + (((x) & 0xF) << 2)) + +#define GUSB2PHYCFG_USBTRDTIM_MASK (0xF << 10) +#define GUSB2PHYCFG_USBTRDTIM(x) (((x) & 0xF) << 10) +#define GUSB2PHYCFG_SUSPHY BIT6 + +#define GUSB3PIPECTL(x) (DW_USB3_BASE + 0xC2C0 + (((x) & 0x3) << 2)) + +#define PIPECTL_DELAYP1TRANS BIT18 +#define PIPECTL_SUSPEND_EN BIT17 +#define PIPECTL_LFPS_FILTER BIT9 +#define PIPECTL_TX_DEMPH_MASK (0x3 << 1) +#define PIPECTL_TX_DEMPH(x) (((x) & 0x3) << 1) + +#define GTXFIFOSIZ(x) (DW_USB3_BASE + 0xC300 + (((x) & 0x1F) << 2)) +#define GRXFIFOSIZ(x) (DW_USB3_BASE + 0xC380 + (((x) & 0x1F) << 2)) + +#define FIFOSIZ_ADDR(x) (((x) & 0xFFFF) << 16) +#define FIFOSIZ_DEP(x) ((x) & 0xFFFF) + +#define GEVNTADRL(x) (DW_USB3_BASE + 0xC400 + (((x) & 0x1F) << 2)) +#define GEVNTADRH(x) (DW_USB3_BASE + 0xC404 + (((x) & 0x1F) << 2)) +#define GEVNTSIZ(x) (DW_USB3_BASE + 0xC408 + (((x) & 0x1F) << 2)) + +#define GEVNTSIZ_EVNTINTMASK BIT31 +#define GEVNTSIZ_EVNTSIZ_MASK (0xFFFF) +#define GEVNTSIZ_EVNTSIZ(x) ((x) & 0xFFFF) + +#define GEVNTCOUNT(x) (DW_USB3_BASE + 0xC40C + (((x) & 0x1F) << 2)) +#define GEVNTCOUNT_EVNTCOUNT_MASK (0xFFFF) +#define GEVNTCOUNT_EVNTCOUNT(x) ((x) & 0xFFFF) + +// Non-Endpoint specific event flag +#define GEVNT_INTTYPE_MASK (0x7F << 1) +#define GEVNT_INTTYPE(x) (((x) & 0x7F) << 1) +#define EVENT_I2C_INT 4 +#define EVENT_CARKIT_INT 3 +#define EVENT_OTG_INT 1 +#define EVENT_DEV_INT 0 + +#define GEVNT_NON_EP BIT0 +// Endpoint specific event flag +#define GEVNT_DEPEVT_INTTYPE_MASK (0xF << 6) +#define GEVNT_DEPEVT_INTTYPE(x) (((x) & 0xF) << 6) +#define GEVNT_DEPEVT_INTTYPE_EPCMD_CMPL (7 << 6) +#define GEVNT_DEPEVT_INTTYPE_STRM_EVT (6 << 6) +#define GEVNT_DEPEVT_INTTYPE_FIFOXRUN (4 << 6) +#define GEVNT_DEPEVT_INTTYPE_XFER_NRDY (3 << 6) +#define GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG (2 << 6) +#define GEVNT_DEPEVT_INTTYPE_XFER_CMPL (1 << 6) +#define GEVNT_DEPEVT_EPNUM_MASK (0x1F << 1) +#define GEVNT_DEPEVT_EPNUM_SHIFT 1 +#define GEVNT_DEPEVT_EPNUM(x) (((x) & 0x1F) << 1) +// Devices specific event flag +#define GEVNT_DEVT_MASK (0xF << 8) +#define GEVNT_DEVT_SHIFT 8 +#define GEVNT_DEVT(x) (((x) & 0xF) << 8) +#define GEVNT_DEVT_INACT_TIMEOUT_RCVD (0x15 << 8) +#define GEVNT_DEVT_VNDR_DEV_TST_RCVD (0x14 << 8) +#define GEVNT_DEVT_OVERFLOW (0x13 << 8) +#define GEVNT_DEVT_CMD_CMPL (0x12 << 8) +#define GEVNT_DEVT_ERRATICERR (0x11 << 8) +#define GEVNT_DEVT_SOF (0x7 << 8) +#define GEVNT_DEVT_EOPF (0x6 << 8) +#define GEVNT_DEVT_HIBER_REQ (0x5 << 8) +#define GEVNT_DEVT_WKUP (0x4 << 8) +#define GEVNT_DEVT_ULST_CHNG (0x3 << 8) +#define GEVNT_DEVT_CONNDONE (0x2 << 8) +#define GEVNT_DEVT_USBRESET (0x1 << 8) +#define GEVNT_DEVT_DISCONN (0x0 << 8) + +#define DCFG (DW_USB3_BASE + 0xC700) + +#define DCFG_NUMP_MASK (0x1F << 17) +#define DCFG_NUMP(x) (((x) & 0x1F) << 17) +#define DCFG_DEVADDR_MASK (0x7F << 3) +#define DCFG_DEVADDR(x) (((x) & 0x7F) << 3) +#define DCFG_DEVSPD_MASK (0x7) +#define DCFG_DEVSPD(x) ((x) & 0x7) +#define DEVSPD_HS_PHY_30MHZ_OR_60MHZ 0 +#define DEVSPD_FS_PHY_30MHZ_OR_60MHZ 1 +#define DEVSPD_LS_PHY_6MHZ 2 +#define DEVSPD_FS_PHY_48MHZ 3 +#define DEVSPD_SS_PHY_125MHZ_OR_250MHZ 4 + +#define DCTL (DW_USB3_BASE + 0xC704) + +#define DCTL_RUN_STOP BIT31 +#define DCTL_CSFTRST BIT30 +#define DCTL_INIT_U2_EN BIT12 +#define DCTL_ACCEPT_U2_EN BIT11 +#define DCTL_INIT_U1_EN BIT10 +#define DCTL_ACCEPT_U1_EN BIT9 + +#define DEVTEN (DW_USB3_BASE + 0xC708) +#define DEVTEN_CONNECTDONEEN BIT2 +#define DEVTEN_USBRSTEN BIT1 +#define DEVTEN_DISCONNEN BIT0 + +#define DSTS (DW_USB3_BASE + 0xC70C) +#define DSTS_GET_DEVSPD(x) ((x) & 0x7) + +#define DALEPENA (DW_USB3_BASE + 0xC720) + +#define DEPCMDPAR2(x) (DW_USB3_BASE + 0xC800 + ((x) & 0x1F) * 0x10) +#define DEPCMDPAR1(x) (DW_USB3_BASE + 0xC804 + ((x) & 0x1F) * 0x10) +#define DEPCMDPAR0(x) (DW_USB3_BASE + 0xC808 + ((x) & 0x1F) * 0x10) +#define DEPCMD(x) (DW_USB3_BASE + 0xc80C + ((x) & 0x1F) * 0x10) + +#define DEPCMD_COMMANDPARAM_MASK (0xFFFF << 16) +#define DEPCMD_COMMANDPARAM(x) (((x) & 0xFFFF) << 16) +/* Stream Number or uFrame (input) */ +#define DEPCMD_STR_NUM_OR_UF_MASK (0xFFFF << 16) +#define DEPCMD_STR_NUM_OR_UF(x) (((x) & 0xFFFF) << 16) +/* Transfer Resource Index (output) */ +#define DEPCMD_XFER_RSRC_IDX_SHIFT 16 +#define DEPCMD_XFER_RSRC_IDX_MASK (0x7F << 16) +#define DEPCMD_XFER_RSRC_IDX(x) (((x) & 0x7F) << 16) +#define GET_DEPCMD_XFER_RSRC_IDX(x) (((x) >> 16) & 0x7F) +#define DEPCMD_CMDACT BIT10 +#define DEPCMD_CMDTYPE_MASK 0xFF +#define DEPCMD_CMDTYPE(x) ((x) & 0xFF) + +/* EP registers range as: OUT0, IN0, OUT1, IN1, ... */ +#define EP_OUT_IDX(x) ((x) * 2) +#define EP_IN_IDX(x) (((x) * 2) + 1) + +#define CMDTYPE_SET_EP_CFG 1 +#define CMDTYPE_SET_XFER_CFG 2 +#define CMDTYPE_GET_EP_STATE 3 +#define CMDTYPE_SET_STALL 4 +#define CMDTYPE_CLR_STALL 5 +#define CMDTYPE_START_XFER 6 +#define CMDTYPE_UPDATE_XFER 7 +#define CMDTYPE_END_XFER 8 +#define CMDTYPE_START_NEW_CFG 9 + +#define EPTYPE_CONTROL 0 +#define EPTYPE_ISOC 1 +#define EPTYPE_BULK 2 +#define EPTYPE_INTR 3 + +#define CFG_ACTION_INIT 0 +#define CFG_ACTION_RESTORE 1 +#define CFG_ACTION_MODIFY 2 + +#define EPCFG0_CFG_ACTION_MASK (0x3 << 30) +#define EPCFG0_CFG_ACTION(x) (((x) & 0x3) << 30) +#define EPCFG0_BRSTSIZ_MASK (0xF << 22) +#define EPCFG0_BRSTSIZ(x) (((x) & 0xF) << 22) +#define EPCFG0_TXFNUM_MASK (0x1F << 17) +#define EPCFG0_TXFNUM(x) (((x) & 0x1F) << 17) +#define EPCFG0_MPS_MASK (0x7FF << 3) +#define EPCFG0_MPS(x) (((x) & 0x7FF) << 3) +#define EPCFG0_EPTYPE_MASK (0x3 << 1) +#define EPCFG0_EPTYPE_SHIFT 1 +#define EPCFG0_EPTYPE(x) (((x) & 0x3) << 1) + +/* Endpoint Number */ +#define EPCFG1_EP_NUM_MASK (0xF << 26) +#define EPCFG1_EP_NUM(x) (((x) & 0xF) << 26) +/* Endpoint Direction */ +#define EPCFG1_EP_DIR_IN BIT25 +/* Stream Not Ready */ +#define EPCFG1_XFER_NRDY BIT10 +/* XferInProgress Enable */ +#define EPCFG1_XFER_IN_PROG BIT9 +/* Stream Completed */ +#define EPCFG1_XFER_CMPL BIT8 + +#define USB_SPEED_UNKNOWN 0 +#define USB_SPEED_LOW 1 +#define USB_SPEED_FULL 2 +#define USB_SPEED_HIGH 3 +#define USB_SPEED_VARIABLE 4 +#define USB_SPEED_SUPER 5 + +// DMA registers +#define DSCSTS_TRBRSP_MASK (0xF << 28) +#define DSCSTS_TRBRSP(x) (((x) & 0xF) << 28) +#define GET_DSCSTS_TRBRSP(x) (((x) >> 28) & 0xF) +#define TRBRSP_MISSED_ISOC_IN 1 +#define TRBRSP_SETUP_PEND 2 +#define TRBRSP_XFER_IN_PROG 4 +#define DSCSTS_PCM1_MASK (0x3 << 24) +#define DSCSTS_PCM1(x) (((x) & 0x3) << 24) +#define DSCSTS_XFERCNT_MASK 0xFFFFFF +#define DSCSTS_XFERCNT(x) ((x) & 0xFFFFFF) +#define GET_DSCSTS_XFERCNT(x) ((x) & 0xFFFFFF) + +#define DSCCTL_STRMID_SOFN(x) (((x) & 0xFFFF) << 14) +#define DSCCTL_IOC BIT11 +#define DSCCTL_ISP BIT10 +#define DSCCTL_TRBCTL_MASK (0x3F << 4) +#define DSCCTL_TRBCTL(x) (((x) & 0x3F) << 4) +#define DSCCTL_LST BIT1 +#define DSCCTL_HWO BIT0 +#define TRBCTL_NORMAL 1 +#define TRBCTL_SETUP 2 +#define TRBCTL_STATUS_2 3 +#define TRBCTL_STATUS_3 4 +#define TRBCTL_CTLDATA_1ST 5 +#define TRBCTL_ISOC_1ST 6 +#define TRBCTL_ISOC 7 +#define TRBCTL_LINK 8 +#define TRBCTL_NORMAL_ZLP 9 + + +#define UE_DIR_IN 0x80 +#define UE_DIR_OUT 0 +#define UE_SET_DIR(a, d) ((a) | (((d) & 1) << 7)) +#define UE_GET_DIR(a) ((a) & 0x80) +#define UE_ADDR 0x0F +#define UE_GET_ADDR(a) ((a) & UE_ADDR) + +#define UT_GET_DIR(a) ((a) & 0x80) +#define UT_WRITE 0x00 +#define UT_READ 0x80 + +#define UT_GET_TYPE(a) ((a) & 0x60) +#define UT_STANDARD 0x00 +#define UT_CLASS 0x20 +#define UT_VENDOR 0x40 + +#define UT_GET_RECIPIENT(a) ((a) & 0x1f) +#define UT_DEVICE 0x00 +#define UT_INTERFACE 0x01 +#define UT_ENDPOINT 0x02 +#define UT_OTHER 0x03 + +#define UR_GET_STATUS 0x00 +#define UR_CLEAR_FEATURE 0x01 +#define UR_SET_FEATURE 0x03 +#define UR_SET_ADDRESS 0x05 +#define UR_GET_DESCRIPTOR 0x06 +#define UR_SET_DESCRIPTOR 0x07 +#define UR_GET_CONFIG 0x08 +#define UR_SET_CONFIG 0x09 +#define UR_GET_INTERFACE 0x0A +#define UR_SET_INTERFACE 0x0B +#define UR_SYNCH_FRAME 0x0C +#define UR_SET_SEL 0x30 +#define UR_SET_ISOC_DELAY 0x31 + +/* Feature numbers */ +#define UF_ENDPOINT_HALT 0 +#define UF_DEVICE_REMOTE_WAKEUP 1 +#define UF_TEST_MODE 2 +#define UF_DEVICE_B_HNP_ENABLE 3 +#define UF_DEVICE_A_HNP_SUPPORT 4 +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 +#define UF_FUNCTION_SUSPEND 0 +#define UF_U1_ENABLE 48 +#define UF_U2_ENABLE 49 +#define UF_LTM_ENABLE 50 + +#define UDESC_DEVICE 0x01 +#define UDESC_CONFIG 0x02 +#define UDESC_STRING 0x03 +#define UDESC_INTERFACE 0x04 +#define UDESC_ENDPOINT 0x05 +#define UDESC_SS_USB_COMPANION 0x30 +#define UDESC_DEVICE_QUALIFIER 0x06 +#define UDESC_BOS 0x0f +#define UDESC_DEVICE_CAPABILITY 0x10 + +#define STRING_LANGUAGE 0 +#define STRING_MANUFACTURER 1 +#define STRING_PRODUCT 2 +#define STRING_SERIAL 3 + +#define CONFIG_VALUE 1 + +#define USB3_BULK_IN_EP 1 +#define USB3_BULK_OUT_EP 1 + +#define USB_ENUM_ADB_PORT_VID 0x18D1 +#define USB_ENUM_ADB_PORT_PID 0xD00D +#define USB_ENUM_INTERFACE_ADB_SUBCLASS 0x42 +#define USB_ENUM_INTERFACE_ADB_PROTOCOL 0x03 + +struct usb3_pcd; + +typedef enum pcd_state { + USB3_STATE_UNCONNECTED, /* no host */ + USB3_STATE_DEFAULT, + USB3_STATE_ADDRESSED, + USB3_STATE_CONFIGURED, +} pcdstate_e; + +typedef enum ep0_state { + EP0_IDLE, + EP0_IN_DATA_PHASE, + EP0_OUT_DATA_PHASE, + EP0_IN_WAIT_NRDY, + EP0_OUT_WAIT_NRDY, + EP0_IN_STATUS_PHASE, + EP0_OUT_STATUS_PHASE, + EP0_STALL, +} ep0state_e; + +typedef struct usb3_dma_desc { + /** Buffer Pointer - Low address quadlet */ + UINT32 bptl; + + /** Buffer Pointer - High address quadlet */ + UINT32 bpth; + + /** Status quadlet. Fields defined in enum @ref desc_sts_data. */ + UINT32 status; + + /** Control quadlet. Fields defined in enum @ref desc_ctl_data. */ + UINT32 control; +} usb3_dma_desc_t; + +typedef struct usb3_pcd_req { + usb3_dma_desc_t *trb; + UINT64 trbdma; + + UINT32 length; + UINT32 actual; + + UINT64 *bufdma; + int (*complete)(unsigned actual, int status); +} usb3_pcd_req_t; + +typedef struct usb_device_request { + UINT8 bmRequestType; + UINT8 bRequest; + UINT16 wValue; + UINT16 wIndex; + UINT16 wLength; +} usb_device_request_t; + +#pragma pack(1) +/** USB_DT_DEVICE: Device descriptor */ +typedef struct usb_device_descriptor { + UINT8 bLength; + UINT8 bDescriptorType; + + UINT16 bcdUSB; +#define USB_CLASS_COMM 0x02 +#define USB_CLASS_VENDOR_SPEC 0xFF +#define USB_SC_VENDOR_SPEC 0xFF +#define USB_PR_VENDOR_SPEC 0xFF + UINT8 bDeviceClass; + UINT8 bDeviceSubClass; + UINT8 bDeviceProtocol; + UINT8 bMaxPacketSize0; + UINT16 idVendor; + UINT16 idProduct; + UINT16 bcdDevice; + UINT8 iManufacturer; + UINT8 iProduct; + UINT8 iSerialNumber; + UINT8 bNumConfigurations; +} usb_device_descriptor_t; + +/* USB_DT_CONFIG: Config descriptor */ +typedef struct usb_config_descriptor { + UINT8 bLength; + UINT8 bDescriptorType; + + UINT16 wTotalLength; + UINT8 bNumInterfaces; +#define CONFIG_VALUE 1 + UINT8 bConfigurationValue; + UINT8 iConfiguration; +#define USB_CONFIG_ATT_ONE (1 << 7) + UINT8 bmAttributes; +#define USB_CONFIG_VBUS_DRAW (0xFA) + UINT8 bMaxPower; +} usb_config_descriptor_t; + +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ +typedef struct usb_qualifier_descriptor { + UINT8 bLength; + UINT8 bDescriptorType; + + UINT16 bcdUSB; + UINT8 bDeviceClass; + UINT8 bDeviceSubClass; + UINT8 bDeviceProtocol; + UINT8 bMaxPacketSize0; + UINT8 bNumConfigurations; + UINT8 bRESERVED; +} usb_qualifier_descriptor_t; + +/* USB_DT_INTERFACE: Interface descriptor */ +typedef struct usb_interface_descriptor { + UINT8 bLength; + UINT8 bDescriptorType; + + UINT8 bInterfaceNumber; + UINT8 bAlternateSetting; + UINT8 bNumEndpoints; + UINT8 bInterfaceClass; + UINT8 bInterfaceSubClass; + UINT8 bInterfaceProtocol; + UINT8 iInterface; +} usb_interface_descriptor_t; + +/* USB_DT_ENDPOINT: Endpoint descriptor */ +typedef struct usb_endpoint_descriptor { + UINT8 bLength; + UINT8 bDescriptorType; + + UINT8 bEndpointAddress; + UINT8 bmAttributes; +#define USB_ENDPOINT_XFER_CONTROL 0x00 +#define USB_ENDPOINT_XFER_ISOC 0x01 +#define USB_ENDPOINT_XFER_BULK 0x02 +#define USB_ENDPOINT_XFER_INT 0x03 + UINT16 wMaxPacketSize; + UINT8 bInterval; +} usb_endpoint_descriptor_t; + +/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ +typedef struct usb_ss_ep_comp_descriptor { + UINT8 bLength; + UINT8 bDescriptorType; + + UINT8 bMaxBurst; + UINT8 bmAttributes; + UINT16 wBytesPerInterval; +} usb_ss_ep_comp_descriptor_t; + +/* WUSB BOS Descriptor (Binary device Object Store) */ +typedef struct wusb_bos_desc { + UINT8 bLength; + UINT8 bDescriptorType; + UINT16 wTotalLength; + UINT8 bNumDeviceCaps; +} wusb_bos_desc_t; + +#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 +typedef struct usb_dev_cap_20_ext_desc { + UINT8 bLength; + UINT8 bDescriptorType; + UINT8 bDevCapabilityType; +#define USB_20_EXT_LPM 0x02 + UINT32 bmAttributes; +} usb_dev_cap_20_ext_desc_t; + +#define USB_DEVICE_CAPABILITY_SS_USB 0x03 +typedef struct usb_dev_cap_ss_usb { + UINT8 bLength; + UINT8 bDescriptorType; + UINT8 bDevCapabilityType; +#define USB_DC_SS_USB_LTM_CAPABLE 0x02 + UINT8 bmAttributes; +#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 +#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 +#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 +#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 + UINT32 wSpeedsSupported; + UINT8 bFunctionalitySupport; + UINT8 bU1DevExitLat; + UINT32 wU2DevExitLat; +} usb_dev_cap_ss_usb_t; + +#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 +typedef struct usb_dev_cap_container_id { + UINT8 bLength; + UINT8 bDescriptorType; + UINT8 bDevCapabilityType; + UINT8 bReserved; + UINT8 containerID[16]; +} usb_dev_cap_container_id_t; +#pragma pack() + +typedef union usb_setup_pkt { + usb_device_request_t req; + UINT32 d32[2]; + UINT8 d8[8]; +} usb_setup_pkt_t; + +typedef struct usb3_pcd_ep { + struct usb3_pcd *pcd; + + UINT8 EpInIdx; + UINT8 EpOutIdx; + UINT8 phys; + + //UINT8 phys; + UINT8 num; + UINT8 type; + UINT8 maxburst; + UINT16 maxpacket; + /* Tx FIFO # for IN EPs */ + UINT8 tx_fifo_num; + + /* The Transfer Resource Index from the Start Transfer command */ + UINT8 tri_out; + UINT8 tri_in; + + UINT8 stopped; + /* Send ZLP */ + UINT8 send_zlp; + /* True if 3-stage control transfer */ + UINT8 three_stage; + /* True if transfer has been started on EP */ + UINT8 xfer_started; + /* EP direction 0 = OUT */ + UINT8 is_in; + /* True if endpoint is active */ + UINT8 active; + /* Initial data pid of bulk endpoint */ + UINT8 data_pid_start; + + /* ep_desc (excluding ep0) */ + usb3_dma_desc_t *ep_desc; + +#if 0 + /* TRB descriptor must be aligned to 16 bytes */ + UINT8 epx_desc[32]; +#endif + + /* request (excluding ep0) */ + usb3_pcd_req_t req; +} usb3_pcd_ep_t; + +typedef struct usb3_pcd { + //struct usb3_device *usb3_dev; + + INT32 link_state; + pcdstate_e state; + UINT8 new_config; + ep0state_e ep0state; + + UINT32 eps_enabled; + UINT32 ltm_enable; + + usb3_pcd_ep_t ep0; + usb3_pcd_ep_t out_ep; + usb3_pcd_ep_t in_ep; + + /* + usb3_dev_global_regs_t *dev_global_regs; + usb3_dev_ep_regs_t *out_ep_regs; + usb3_dev_ep_regs_t *in_ep_regs; + */ + + usb3_pcd_req_t ep0_req; + + UINT8 speed; + + usb3_dma_desc_t *ep0_setup_desc; + usb3_dma_desc_t *ep0_in_desc; + usb3_dma_desc_t *ep0_out_desc; + + /* TRB descriptor must be aligned to 16 bytes */ +#if 0 + UINT8 ep0_setup[32]; + UINT8 ep0_in[32]; + UINT8 ep0_out[32]; + + usb_setup_pkt_t ep0_setup_pkt[5]; + +#define USB3_STATUS_BUF_SIZE 512 + UINT8 ep0_status_buf[USB3_STATUS_BUF_SIZE]; + +#define USB3_BULK_BUF_SIZE 2048 + UINT8 ss_bulk_buf[USB3_BULK_BUF_SIZE]; +#endif + + UINT32 file_type; + UINT32 file_address; + UINT32 file_capacity; + UINT32 file_total_frame; + UINT32 file_curr_frame; + UINT32 file_next_frame; + UINT32 file_received; + UINT32 file_complete; + + UINT16 test_mode_nr; + UINT16 test_mode; +} usb3_pcd_t; + +struct usb_enum_port_param { + UINT16 idVendor; + UINT16 idProduct; + UINT8 bInterfaceSubClass; + UINT8 bInterfaceProtocol; +}; + +#if 0 +typedef struct usb3_pcd_req { + usb3_dma_desc_t *trb; + UINT64 trbdma; + + UINT32 length; + UINT32 actual; + + UINT64 *bufdma; + int (*complete)(unsigned actual, int status); +} usb3_pcd_req_t; + +#endif + +#endif /* __DW_USB3_DXE_H__ */ diff --git a/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c new file mode 100644 index 000000000000..83d5e4736de0 --- /dev/null +++ b/EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c @@ -0,0 +1,2434 @@ +/** @file + + Copyright (c) 2018, Linaro Limited. All rights reserved. + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <IndustryStandard/Usb.h> +#include <Library/ArmLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/CacheMaintenanceLib.h> +#include <Library/DebugLib.h> +#include <Library/DmaLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/TimerLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Protocol/DwUsb.h> +#include <Protocol/DriverBinding.h> +#include <Protocol/UsbDevice.h> + +#include "DwUsb3Dxe.h" + +#define FIFO_DIR_TX 0 +#define FIFO_DIR_RX 1 + +#define TX_FIFO_ADDR 0 +#define RX_FIFO_ADDR 0 + +#define RAM_WIDTH 8 +#define RAM_TX0_DEPTH 2048 +#define RAM_TX1_DEPTH 4096 +#define RAM_RX_DEPTH 8192 + +#define USB_TYPE_LENGTH 16 +#define USB_BLOCK_HIGH_SPEED_SIZE 512 +#define DATA_SIZE 131072 +#define CMD_SIZE 512 +#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1) + +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) + +// +// The time between interrupt polls, in units of 100 nanoseconds +// 10 Microseconds +// +#define DW_INTERRUPT_POLL_PERIOD 100 + +#define DWUSB3_EVENT_BUF_SIZE 256 + +// +// Maxpacket size for EP0, defined by USB3 spec +// +#define USB3_MAX_EP0_SIZE 512 + +// +// Maxpacket size for any EP, defined by USB3 spec +// +#define USB3_MAX_PACKET_SIZE 1024 +#define USB2_HS_MAX_PACKET_SIZE 512 +#define USB2_FS_MAX_PACKET_SIZE 64 + +#define USB3_STATE_UNCONNECTED 0 +#define USB3_STATE_DEFAULT 1 +#define USB3_STATE_ADDRESSED 2 +#define USB3_STATE_CONFIGURED 3 + +#define USB3_STATUS_BUF_SIZE 512 + +#define GET_EVENTBUF_COUNT() \ + (GEVNTCOUNT_EVNTCOUNT (MmioRead32 (GEVNTCOUNT (0)))) +#define UPDATE_EVENTBUF_COUNT(x) \ + (MmioWrite32 (GEVNTCOUNT (0), GEVNTCOUNT_EVNTCOUNT (x))) + +#define SET_DEVADDR(x) \ + (MmioAndThenOr32 (DCFG, ~DCFG_DEVADDR_MASK, DCFG_DEVADDR (x))) + +EFI_GUID gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID; + +STATIC DW_USB_PROTOCOL *DwUsb; + +STATIC usb3_pcd_t gPcd; +STATIC UINT32 *gEventBuf, *gEventPtr; +STATIC struct usb_device_descriptor gDwUsb3DevDesc; +STATIC VOID *gRxBuf; + +STATIC usb_setup_pkt_t *gEndPoint0SetupPacket; +STATIC UINT8 *gEndPoint0StatusBuf; +STATIC USB_DEVICE_RX_CALLBACK mDataReceivedCallback; +STATIC UINTN mDataBufferSize; + +struct usb_interface_descriptor intf = { + sizeof (struct usb_interface_descriptor), + UDESC_INTERFACE, + 0, + 0, + 2, + USB_CLASS_VENDOR_SPEC, + 0x42, + 0x03, + 0 +}; + +const struct usb_ss_ep_comp_descriptor ep_comp = { + sizeof (struct usb_ss_ep_comp_descriptor), + UDESC_SS_USB_COMPANION, + 0, + 0, + 0 +}; + +const struct usb_endpoint_descriptor hs_bulk_in = { + sizeof (struct usb_endpoint_descriptor), + UDESC_ENDPOINT, + UE_DIR_IN | USB3_BULK_IN_EP, + USB_ENDPOINT_XFER_BULK, + 0x200, + 0 +}; + +const struct usb_endpoint_descriptor +hs_bulk_out = { + sizeof(struct usb_endpoint_descriptor), /* bLength */ + UDESC_ENDPOINT, /* bDescriptorType */ + + UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */ + USB_ENDPOINT_XFER_BULK, /* bmAttributes */ + 0x200, /* wMaxPacketSize: 512 of high-speed */ + 1, /* bInterval */ +}; + +const struct usb_endpoint_descriptor ss_bulk_in = { + sizeof(struct usb_endpoint_descriptor), /* bLength */ + UDESC_ENDPOINT, /* bDescriptorType */ + + UE_DIR_IN | USB3_BULK_IN_EP, /* bEndpointAddress */ + USB_ENDPOINT_XFER_BULK, /* bmAttributes */ + 0x400, /* wMaxPacketSize: 1024 of super-speed */ + 0, /* bInterval */ +}; + +const struct usb_endpoint_descriptor ss_bulk_out = { + sizeof(struct usb_endpoint_descriptor), /* bLength */ + UDESC_ENDPOINT, /* bDescriptorType */ + + UE_DIR_OUT | USB3_BULK_OUT_EP, /* bEndpointAddress */ + USB_ENDPOINT_XFER_BULK, /* bmAttributes */ + 0x400, /* wMaxPacketSize: 1024 of super-speed */ + 0, /* bInterval */ +}; + +/** The BOS Descriptor */ + +const struct usb_dev_cap_20_ext_desc cap1 = { + sizeof(struct usb_dev_cap_20_ext_desc), /* bLength */ + UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ + USB_DEVICE_CAPABILITY_20_EXTENSION, /* bDevCapabilityType */ + 0x2, /* bmAttributes */ +}; + +const struct usb_dev_cap_ss_usb +cap2 = { + sizeof(struct usb_dev_cap_ss_usb), /* bLength */ + UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ + USB_DEVICE_CAPABILITY_SS_USB, /* bDevCapabilityType */ + 0x0, /* bmAttributes */ + (USB_DC_SS_USB_SPEED_SUPPORT_SS | + USB_DC_SS_USB_SPEED_SUPPORT_HIGH), /* wSpeedsSupported */ + 0x2, /* bFunctionalitySupport */ + 0xa, /* bU1DevExitLat */ + 0x100, /* wU2DevExitLat */ +}; + +const struct usb_dev_cap_container_id +cap3 = { + sizeof(struct usb_dev_cap_container_id),/* bLength */ + UDESC_DEVICE_CAPABILITY, /* bDescriptorType */ + USB_DEVICE_CAPABILITY_CONTAINER_ID, /* bDevCapabilityType */ + 0, /* bReserved */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* containerID */ +}; + +const struct wusb_bos_desc +bos = { + sizeof(struct wusb_bos_desc), /* bLength */ + UDESC_BOS, /* bDescriptorType */ + (sizeof(struct wusb_bos_desc) + \ + sizeof(cap1) + sizeof(cap2) + \ + sizeof(cap3)), /* wTotalLength */ + 3, /* bNumDeviceCaps */ +}; + +STATIC struct usb_enum_port_param usb_port_activity_config = { + .idVendor = USB_ENUM_ADB_PORT_VID, + .idProduct = USB_ENUM_ADB_PORT_PID, + .bInterfaceSubClass = USB_ENUM_INTERFACE_ADB_SUBCLASS, + .bInterfaceProtocol = USB_ENUM_INTERFACE_ADB_PROTOCOL +}; + +STATIC +UINT32 +DwUsb3GetEventBufEvent ( + IN UINTN Size + ) +{ + UINT32 Event; + + Event = *gEventPtr++; + if ((UINT32)(UINTN)gEventPtr >= (UINT32)(UINTN)gEventBuf + Size) { + gEventPtr = gEventBuf; + } + return Event; +} + +STATIC +VOID +DwUsb3SetFifoSize ( + IN UINT32 Addr, + IN UINT32 Depth, + IN UINT32 Dir, + IN UINT32 FifoNum + ) +{ + UINT32 Reg = 0; + + if (Dir == FIFO_DIR_TX) { + Reg = GTXFIFOSIZ (FifoNum); + } else if (Dir == FIFO_DIR_RX) { + Reg = GRXFIFOSIZ (FifoNum); + } else { + ASSERT (0); + } + MmioWrite32 (Reg, FIFOSIZ_DEP (Depth) | FIFOSIZ_ADDR (Addr)); +} + +STATIC +UINT32 +Handshake ( + IN UINT32 Reg, + IN UINT32 Mask, + IN UINT32 Done + ) +{ + UINT32 Timeout = 100000; + + do { + if ((MmioRead32 (Reg) & Mask) == Done) { + return 1; + } + MicroSecondDelay (1); + } while (Timeout-- > 0); + return 0; +} + +STATIC +VOID +DwUsb3FillDesc ( + IN usb3_dma_desc_t *desc, + IN UINT64 dma_addr, + IN UINT32 dma_len, + IN UINT32 stream, + IN UINT32 type, + IN UINT32 ctrlbits, + IN UINT32 own + ) +{ + desc->bptl = (UINT32)(dma_addr & 0xFFFFFFFF); + desc->bpth = (UINT32)(dma_addr >> 32); + desc->status = DSCSTS_XFERCNT (dma_len); + if (type) { + desc->control = DSCCTL_TRBCTL (type); + } + desc->control |= DSCCTL_STRMID_SOFN (stream) | ctrlbits; + ArmDataSynchronizationBarrier (); + /* must execute this operation at last */ + if (own) { + desc->control |= DSCCTL_HWO; + } + ArmDataSynchronizationBarrier (); +} + +STATIC +VOID +DwUsb3DepStartNewCfg ( + IN UINT32 EpIdx, + IN UINT32 RsrcIdx + ) +{ + /* start the command */ + MmioWrite32 ( + DEPCMD (EpIdx), + DEPCMD_XFER_RSRC_IDX (RsrcIdx) | DEPCMD_CMDTYPE (CMDTYPE_START_NEW_CFG) | \ + DEPCMD_CMDACT + ); + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); +} + +STATIC +VOID +DwUsb3DepCfg ( + IN UINT32 EpIdx, + IN UINT32 DepCfg0, + IN UINT32 DepCfg1, + IN UINT32 DepCfg2 + ) +{ + MmioWrite32 (DEPCMDPAR2 (EpIdx), DepCfg2); + MmioWrite32 (DEPCMDPAR1 (EpIdx), DepCfg1); + MmioWrite32 (DEPCMDPAR0 (EpIdx), DepCfg0); + MmioWrite32 ( + DEPCMD (EpIdx), + DEPCMD_CMDTYPE (CMDTYPE_SET_EP_CFG) | DEPCMD_CMDACT + ); + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); +} + +STATIC +VOID +DwUsb3DepXferCfg ( + IN UINT32 EpIdx, + IN UINT32 DepStrmCfg + ) +{ + MmioWrite32 (DEPCMDPAR0 (EpIdx), DepStrmCfg); + MmioWrite32 ( + DEPCMD (EpIdx), + DEPCMD_CMDTYPE (CMDTYPE_SET_XFER_CFG) | DEPCMD_CMDACT + ); + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); +} + +STATIC +UINT8 +DwUsb3DepStartXfer ( + IN UINT32 EpIdx, + IN UINT64 DmaAddr, + IN UINT32 StreamOrUf + ) +{ + UINT32 Data; + + MmioWrite32 (DEPCMDPAR1 (EpIdx), (UINT32)DmaAddr); + MmioWrite32 (DEPCMDPAR0 (EpIdx), (UINT32)(DmaAddr >> 32)); + MmioWrite32 ( + DEPCMD (EpIdx), + DEPCMD_STR_NUM_OR_UF (StreamOrUf) | DEPCMD_CMDTYPE (CMDTYPE_START_XFER) | \ + DEPCMD_CMDACT + ); + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); + Data = MmioRead32 (DEPCMD (EpIdx)); + return GET_DEPCMD_XFER_RSRC_IDX(Data); +} + +STATIC +VOID +DwUsb3DepStopXfer ( + IN UINT32 EpIdx, + IN UINT32 Tri + ) +{ + MmioWrite32 (DEPCMDPAR2 (EpIdx), 0); + MmioWrite32 (DEPCMDPAR1 (EpIdx), 0); + MmioWrite32 (DEPCMDPAR0 (EpIdx), 0); + MmioWrite32 ( + DEPCMD (EpIdx), + DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_END_XFER) | \ + DEPCMD_CMDACT + ); + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); +} + +VOID +DwUsb3DepUpdateXfer ( + IN UINT32 EpIdx, + IN UINT32 Tri + ) +{ + MmioWrite32 ( + DEPCMD (EpIdx), + DEPCMD_XFER_RSRC_IDX (Tri) | DEPCMD_CMDTYPE (CMDTYPE_UPDATE_XFER) | \ + DEPCMD_CMDACT + ); + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); +} + +STATIC +VOID +DwUsb3DepClearStall ( + IN UINTN EpIdx + ) +{ + MmioWrite32 ( + DEPCMD (EpIdx), + DEPCMD_CMDTYPE (CMDTYPE_CLR_STALL) | DEPCMD_CMDACT + ); + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); +} + + +STATIC +VOID +DwUsb3DepSetStall ( + IN UINTN EpIdx + ) +{ + MmioWrite32 ( + DEPCMD (EpIdx), + DEPCMD_CMDTYPE (CMDTYPE_SET_STALL) | DEPCMD_CMDACT + ); + Handshake (DEPCMD (EpIdx), DEPCMD_CMDACT, 0); +} + +STATIC +VOID +DwUsb3EnableEp ( + IN UINT32 EpIdx, + IN usb3_pcd_ep_t *ep + ) +{ + UINT32 Dalepena; + + Dalepena = MmioRead32 (DALEPENA); + /* If the EP is already enabled, skip to set it again. */ + if (Dalepena & (1 << EpIdx)) { + return; + } + Dalepena |= 1 << EpIdx; + MmioWrite32 (DALEPENA, Dalepena); +} + +STATIC +VOID +DwUsb3Ep0Activate ( + IN OUT usb3_pcd_t *pcd + ) +{ + /* issue DEPCFG command to EP0 OUT */ + DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 0); + DwUsb3DepCfg ( + EP_OUT_IDX (0), + EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512), + EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY, + 0 + ); + /* issue DEPSTRMCFG command to EP0 OUT */ + DwUsb3DepXferCfg (EP_OUT_IDX (0), 1); // one stream + /* issue DEPCFG command to EP0 IN */ + DwUsb3DepCfg ( + EP_IN_IDX (0), + EPCFG0_EPTYPE (EPTYPE_CONTROL) | EPCFG0_MPS (512) | \ + EPCFG0_TXFNUM (pcd->ep0.tx_fifo_num), + EPCFG1_XFER_NRDY | EPCFG1_XFER_CMPL | EPCFG1_EP_DIR_IN, + 0 + ); + /* issue DEPSTRMCFG command to EP0 IN */ + DwUsb3DepXferCfg (EP_IN_IDX (0), 1); // one stream + pcd->ep0.active = 1; +} + +STATIC +VOID +DwUsb3EpActivate ( + IN OUT usb3_pcd_t *pcd, + IN OUT usb3_pcd_ep_t *ep + ) +{ + UINT32 EpIdx, DepCfg0, DepCfg1; + if (ep->is_in) { + EpIdx = EP_IN_IDX (ep->num); + } else { + EpIdx = EP_OUT_IDX (ep->num); + } + + /* Start a new configurate when enable the first EP. */ + if (!pcd->eps_enabled) { + pcd->eps_enabled = 1; + /* Issue DEPCFG command to physical EP1 (logical EP0 IN) first. + * It resets the core's Tx FIFO mapping table. + */ + DepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL); + DepCfg0 |= EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY); + DepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY | EPCFG1_EP_DIR_IN; + + switch (pcd->speed) { + case USB_SPEED_SUPER: + DepCfg0 |= EPCFG0_MPS (512); + break; + case USB_SPEED_HIGH: + case USB_SPEED_FULL: + DepCfg0 |= EPCFG0_MPS (64); + break; + case USB_SPEED_LOW: + DepCfg0 |= EPCFG0_MPS (8); + break; + default: + ASSERT (0); + break; + } + DwUsb3DepCfg (EP_IN_IDX (0), DepCfg0, DepCfg1, 0); + DwUsb3DepStartNewCfg (EP_OUT_IDX (0), 2); + } + /* issue DEPCFG command to EP */ + DepCfg0 = EPCFG0_EPTYPE (ep->type); + DepCfg0 |= EPCFG0_MPS (ep->maxpacket); + if (ep->is_in) { + DepCfg0 |= EPCFG0_TXFNUM (ep->tx_fifo_num); + } + DepCfg0 |= EPCFG0_BRSTSIZ (ep->maxburst); + DepCfg1 = EPCFG1_EP_NUM (ep->num); + if (ep->is_in) { + DepCfg1 |= EPCFG1_EP_DIR_IN; + } else { + DepCfg1 |= EPCFG1_XFER_CMPL; + } + DwUsb3DepCfg (EpIdx, DepCfg0, DepCfg1, 0); + /* issue DEPSTRMCFG command to EP */ + DwUsb3DepXferCfg (EpIdx, 1); + DwUsb3EnableEp (EpIdx, ep); + ep->active = 1; +} + +STATIC +VOID +DwUsb3Ep0OutStart ( + IN usb3_pcd_t *pcd + ) +{ + usb3_dma_desc_t *desc; + + /* Get the SETUP packet DMA Descriptor (TRB) */ + desc = pcd->ep0_setup_desc; + + /* DMA Descriptor setup */ + DwUsb3FillDesc ( + desc, + (UINT64)gEndPoint0SetupPacket, + pcd->ep0.maxpacket, + 0, + TRBCTL_SETUP, + DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST, + 1 + ); + + /* issue DEPSTRTXFER command to EP0 OUT */ + pcd->ep0.tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), (UINT64)desc, 0); +} + +STATIC +VOID +DwUsb3Init ( + VOID + ) +{ + UINT32 Data, Addr; + usb3_pcd_t *pcd = &gPcd; + + /* soft reset the usb core */ + do { + MmioAndThenOr32 (DCTL, ~DCTL_RUN_STOP, DCTL_CSFTRST); + + do { + MicroSecondDelay (1000); + Data = MmioRead32 (DCTL); + } while (Data & DCTL_CSFTRST); + // + // wait for at least 3 PHY clocks + // + MicroSecondDelay (1000); + } while (0); + + pcd->link_state = 0; + + /* TI PHY: Set Turnaround Time = 9 (8-bit UTMI+ / ULPI) */ + MmioAndThenOr32 ( + GUSB2PHYCFG (0), + ~GUSB2PHYCFG_USBTRDTIM_MASK, + GUSB2PHYCFG_USBTRDTIM (9) + ); + + /* set TX FIFO size */ + Addr = TX_FIFO_ADDR; + DwUsb3SetFifoSize (Addr, RAM_TX0_DEPTH / RAM_WIDTH, FIFO_DIR_TX, 0); + Addr += RAM_TX0_DEPTH / RAM_WIDTH; + DwUsb3SetFifoSize (Addr, RAM_TX1_DEPTH / RAM_WIDTH, FIFO_DIR_TX, 1); + /* set RX FIFO size */ + DwUsb3SetFifoSize (RX_FIFO_ADDR, RAM_RX_DEPTH / RAM_WIDTH, FIFO_DIR_RX, 0); + + /* set LFPS filter delay1trans */ + MmioAndThenOr32 ( + GUSB3PIPECTL (0), + ~PIPECTL_DELAYP1TRANS, + PIPECTL_LFPS_FILTER | PIPECTL_TX_DEMPH (1) + ); + + /* set GCTL */ + Data = GCTL_U2EXIT_LFPS | GCTL_PRTCAPDIR_DEVICE | GCTL_U2RSTECN | + GCTL_PWRDNSCALE(2); + MmioWrite32 (GCTL, Data); + + /* init event buf */ + MmioWrite32 (GEVNTADRL(0), (UINT32)(UINTN)gEventBuf); + MmioWrite32 (GEVNTADRH(0), (UINTN)gEventBuf >> 32); + MmioWrite32 (GEVNTSIZ(0), DWUSB3_EVENT_BUF_SIZE << 2); + MmioWrite32 (GEVNTCOUNT(0), 0); + + /* set max speed to super speed */ + MmioAndThenOr32 ( + DCFG, + ~DCFG_DEVSPD_MASK, + DCFG_DEVSPD (DEVSPD_SS_PHY_125MHZ_OR_250MHZ) + ); + + /* set nump */ + MmioAndThenOr32 (DCFG, ~DCFG_NUMP_MASK, DCFG_NUMP (16)); + + /* init address */ + SET_DEVADDR (0); + + /* disable phy suspend */ + MmioAnd32 (GUSB3PIPECTL (0), ~PIPECTL_SUSPEND_EN); + MmioAnd32 (GUSB2PHYCFG (0), ~GUSB2PHYCFG_SUSPHY); + + /* clear any pending interrupts */ + Data = MmioRead32 (GEVNTCOUNT (0)); + MmioWrite32 (GEVNTCOUNT (0), Data); + /* enable device interrupts */ + MmioWrite32 (DEVTEN, DEVTEN_CONNECTDONEEN | DEVTEN_USBRSTEN); + /* activate EP0 */ + DwUsb3Ep0Activate (pcd); + /* start EP0 to receive SETUP packets */ + DwUsb3Ep0OutStart (pcd); + + /* enable EP0 OUT/IN in DALEPENA */ + MmioWrite32 (DALEPENA, (1 << EP_OUT_IDX (0)) | (1 << EP_IN_IDX (0))); + + /* set RUN/STOP bit */ + MmioOr32 (DCTL, DCTL_RUN_STOP); +} + +STATIC +VOID +DriverInit ( + VOID + ) +{ + usb3_pcd_t *pcd = &gPcd; + usb3_pcd_ep_t *ep; + EFI_STATUS Status; + + pcd->speed = USB_SPEED_UNKNOWN; + + // + // init EP0 + // + ep = &pcd->ep0; + ep->pcd = pcd; + ep->stopped = 1; + ep->is_in = 0; + ep->active = 0; + ep->phys = 0; + ep->num = 0; + ep->tx_fifo_num = 0; + ep->type = EPTYPE_CONTROL; + ep->maxburst = 0; + ep->maxpacket = USB3_MAX_EP0_SIZE; + ep->send_zlp = 0; + ep->req.length = 0; + ep->req.actual = 0; + pcd->ep0_req.length = 0; + pcd->ep0_req.actual = 0; + + // + // init EP1 OUT + // + ep = &pcd->out_ep; + ep->pcd = pcd; + ep->stopped = 1; + ep->is_in = 0; + ep->active = 0; + ep->phys = USB3_BULK_OUT_EP << 1; + ep->num = 1; + ep->tx_fifo_num = 0; + // + // bulk ep is activated + // + ep->type = EPTYPE_BULK; + ep->maxburst = 0; + ep->maxpacket = USB3_MAX_PACKET_SIZE; + ep->send_zlp = 0; + ep->req.length = 0; + ep->req.actual = 0; + + // + // init EP1 IN + // + ep = &pcd->in_ep; + ep->stopped = 1; + ep->is_in = 1; + ep->active = 0; + ep->phys = (USB3_BULK_IN_EP << 1) | 1; + ep->num = 1; + ep->tx_fifo_num = USB3_BULK_IN_EP; + // + // bulk ep is activated + // + ep->type = EPTYPE_BULK; + ep->maxburst = 0; + ep->maxpacket = USB3_MAX_PACKET_SIZE; + ep->send_zlp = 0; + ep->req.length = 0; + ep->req.actual = 0; + + pcd->ep0state = EP0_IDLE; + pcd->ep0.maxpacket = USB3_MAX_EP0_SIZE; + pcd->ep0.type = EPTYPE_CONTROL; + + Status = DmaAllocateBuffer ( + EfiBootServicesData, + EFI_SIZE_TO_PAGES (sizeof (usb3_dma_desc_t) * 5), + (VOID *)&pcd->ep0_setup_desc + ); + if (EFI_ERROR (Status)) { + return; + } + pcd->ep0_in_desc = pcd->ep0_setup_desc++; + pcd->ep0_out_desc = pcd->ep0_in_desc++; + pcd->in_ep.ep_desc = pcd->ep0_out_desc++; + pcd->out_ep.ep_desc = pcd->in_ep.ep_desc++; +} + +STATIC +VOID +DwUsb3HandleUsbResetInterrupt ( + IN usb3_pcd_t *pcd + ) +{ + usb3_pcd_ep_t *ep; + + // + // clear stall on each EP + // + ep = &pcd->in_ep; + if (ep->xfer_started) { + if (ep->is_in) { + DwUsb3DepStopXfer (EP_IN_IDX (ep->num), ep->tri_in); + } else { + DwUsb3DepStopXfer (EP_OUT_IDX (ep->num), ep->tri_out); + } + } + if (ep->stopped) { + if (ep->is_in) { + DwUsb3DepClearStall (EP_IN_IDX (ep->num)); + } else { + DwUsb3DepClearStall (EP_OUT_IDX (ep->num)); + } + } + + ep = &pcd->out_ep; + if (ep->xfer_started) { + if (ep->is_in) { + DwUsb3DepStopXfer (EP_IN_IDX (ep->num), ep->tri_in); + } else { + DwUsb3DepStopXfer (EP_OUT_IDX (ep->num), ep->tri_out); + } + } + if (ep->stopped) { + if (ep->is_in) { + DwUsb3DepClearStall (EP_IN_IDX (ep->num)); + } else { + DwUsb3DepClearStall (EP_OUT_IDX (ep->num)); + } + } + + // + // set device address to 0 + // + SET_DEVADDR (0); + + pcd->ltm_enable = 0; + DEBUG ((DEBUG_INFO, "usb reset\n")); +} + +STATIC +UINT32 +DwUsb3GetDeviceSpeed ( + IN usb3_pcd_t *pcd + ) +{ + UINT32 Data, Speed; + + Data = MmioRead32 (DSTS); + switch (DSTS_GET_DEVSPD (Data)) { + case DEVSPD_HS_PHY_30MHZ_OR_60MHZ: + Speed = USB_SPEED_HIGH; + break; + case DEVSPD_FS_PHY_30MHZ_OR_60MHZ: + case DEVSPD_FS_PHY_48MHZ: + Speed = USB_SPEED_FULL; + break; + case DEVSPD_LS_PHY_6MHZ: + Speed = USB_SPEED_LOW; + break; + case DEVSPD_SS_PHY_125MHZ_OR_250MHZ: + Speed = USB_SPEED_SUPER; + break; + default: + DEBUG ((DEBUG_ERROR, "DwUsb3GetDeviceSpeed: invalid DSTS:0x%x\n", Data)); + Speed = USB_SPEED_UNKNOWN; + break; + } + return Speed; +} + +STATIC +VOID +DwUsb3PcdSetSpeed ( + IN usb3_pcd_t *pcd, + IN UINTN speed + ) +{ + // + // set the MPS of EP0 based on the connection speed + // + switch (speed) { + case USB_SPEED_SUPER: + pcd->ep0.maxpacket = 512; + pcd->in_ep.maxpacket = USB3_MAX_PACKET_SIZE; + pcd->out_ep.maxpacket = USB3_MAX_PACKET_SIZE; + break; + case USB_SPEED_HIGH: + pcd->ep0.maxpacket = 64; + pcd->in_ep.maxpacket = USB2_HS_MAX_PACKET_SIZE; + pcd->out_ep.maxpacket = USB2_HS_MAX_PACKET_SIZE; + break; + case USB_SPEED_FULL: + pcd->ep0.maxpacket = 64; + pcd->in_ep.maxpacket = USB2_FS_MAX_PACKET_SIZE; + pcd->out_ep.maxpacket = USB2_FS_MAX_PACKET_SIZE; + break; + default: + DEBUG ((DEBUG_ERROR, "invalid speed: %d\n", speed)); + break; + } +} + +STATIC +VOID +DwUsb3HandleConnectDoneInterrupt ( + IN usb3_pcd_t *pcd + ) +{ + usb3_pcd_ep_t *ep0 = &pcd->ep0; + UINT32 DiepCfg0, DoepCfg0, DiepCfg1, DoepCfg1; + UINT32 Speed; + + ep0->stopped = 0; + Speed = (UINT32)DwUsb3GetDeviceSpeed (pcd); + pcd->speed = (UINT8)Speed; + + DwUsb3PcdSetSpeed (pcd, Speed); + // + // set the MPS of EP0 based on the connection speed + // + DiepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL) | \ + EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY); + DiepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY | \ + EPCFG1_EP_DIR_IN; + DoepCfg0 = EPCFG0_EPTYPE (EPTYPE_CONTROL) | \ + EPCFG0_CFG_ACTION (CFG_ACTION_MODIFY); + DoepCfg1 = EPCFG1_XFER_CMPL | EPCFG1_XFER_NRDY; + + switch (Speed) { + case USB_SPEED_SUPER: + DiepCfg0 |= EPCFG0_MPS (512); + DoepCfg0 |= EPCFG0_MPS (512); + break; + case USB_SPEED_HIGH: + case USB_SPEED_FULL: + DiepCfg0 |= EPCFG0_MPS (64); + DoepCfg0 |= EPCFG0_MPS (64); + break; + case USB_SPEED_LOW: + DiepCfg0 |= EPCFG0_MPS (8); + DoepCfg0 |= EPCFG0_MPS (8); + break; + default: + DEBUG (( + DEBUG_ERROR, + "DwUsb3HandleConnectDoneInterrupt: invalid speed %d\n", + Speed + )); + break; + } + DiepCfg0 |= EPCFG0_TXFNUM (ep0->tx_fifo_num); + // + // issue DEPCFG command to EP0 OUT + // + DwUsb3DepCfg (EP_OUT_IDX (0), DoepCfg0, DoepCfg1, 0); + // + // issue DEPCFG command to EP0 IN + // + DwUsb3DepCfg (EP_IN_IDX (0), DiepCfg0, DiepCfg1, 0); + pcd->state = USB3_STATE_DEFAULT; +} + +STATIC +VOID +DwUsb3HandleDeviceInterrupt ( + IN usb3_pcd_t *pcd, + IN UINT32 Event + ) +{ + switch (Event & GEVNT_DEVT_MASK) { + case GEVNT_DEVT_USBRESET: + DwUsb3HandleUsbResetInterrupt (pcd); + break; + case GEVNT_DEVT_CONNDONE: + DwUsb3HandleConnectDoneInterrupt (pcd); + break; + default: + DEBUG ((DEBUG_ERROR, "DwUsb3HandleDeviceInterrupt: invalid event\n")); + break; + } +} + +STATIC +usb3_pcd_ep_t * +DwUsb3GetOutEndPoint ( + IN usb3_pcd_t *pcd, + IN UINT32 EndPointNum + ) +{ + if (EndPointNum == 0) { + return &pcd->ep0; + } + return &pcd->out_ep; +} + +STATIC +usb3_pcd_ep_t * +DwUsb3GetInEndPoint ( + IN usb3_pcd_t *pcd, + IN UINT32 EndPointNum + ) +{ + if (EndPointNum == 0) { + return &pcd->ep0; + } + return &pcd->in_ep; +} + +STATIC +VOID +EndPoint0DoStall ( + IN usb3_pcd_t *pcd + ) +{ + usb3_pcd_ep_t *ep0 = &pcd->ep0; + + // + // stall EP0 IN & OUT simultanelusly + // + ep0->is_in = 1; + DwUsb3DepSetStall (EP_IN_IDX (0)); + ep0->is_in = 0; + DwUsb3DepSetStall (EP_OUT_IDX (0)); + // + // prepare for the next setup transfer + // + ep0->stopped = 1; + pcd->ep0state = EP0_IDLE; + DwUsb3Ep0OutStart (pcd); +} + +STATIC +VOID +EndPoint0ContinueTransfer ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_req_t *req + ) +{ + usb3_pcd_ep_t *ep0 = &pcd->ep0; + usb3_dma_desc_t *desc; + UINT64 desc_dma; + UINT8 tri; + + // + // send a 0-byte length packet after the end of transfer + // + if (ep0->is_in) { + desc = pcd->ep0_in_desc; + desc_dma = (UINT64)pcd->ep0_in_desc; + // + // DMA descriptor setup + // + DwUsb3FillDesc ( + desc, + (UINT64)req->bufdma, + 0, + 0, + TRBCTL_NORMAL, + DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST, + 1 + ); + tri = DwUsb3DepStartXfer (EP_IN_IDX (0), desc_dma, 0); + ep0->tri_in = tri; + } +} + +STATIC +VOID +EndPoint0CompleteRequest ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_req_t *req, + IN usb3_dma_desc_t *desc + ) +{ + usb3_pcd_ep_t *ep = &pcd->ep0; + + if (req == NULL) { + return; + } + + if ((pcd->ep0state == EP0_OUT_DATA_PHASE) || + (pcd->ep0state == EP0_IN_DATA_PHASE)) { + if (ep->is_in) { + if (GET_DSCSTS_XFERCNT (desc->status) == 0) { + pcd->ep0.is_in = 0; + pcd->ep0state = EP0_OUT_WAIT_NRDY; + } + } else { + pcd->ep0.is_in = 1; + pcd->ep0state = EP0_IN_WAIT_NRDY; + } + } +} + +STATIC +VOID +DwUsb3OsGetTrb ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_ep_t *ep, + IN usb3_pcd_req_t *req + ) +{ + // + // If EP0, fill request with EP0 IN/OUT data TRB + // + if (ep == &pcd->ep0) { + if (ep->is_in) { + req->trb = pcd->ep0_in_desc; + req->trbdma = (UINT64)pcd->ep0_in_desc; + } else { + req->trb = pcd->ep0_out_desc; + req->trbdma = (UINT64)pcd->ep0_out_desc; + } + } else { + // + // fill request with TRB from the non-EP0 allocation + // + req->trb = ep->ep_desc; + req->trbdma = (UINT64)ep->ep_desc; + } +} + +STATIC +VOID +DwUsb3EndPoint0StartTransfer ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_req_t *req + ) +{ + usb3_pcd_ep_t *ep0 = &pcd->ep0; + usb3_dma_desc_t *desc; + UINT64 desc_dma; + UINT32 desc_type, len; + + // + // get the DMA descriptor (TRB) for this request + // + DwUsb3OsGetTrb (pcd, ep0, req); + desc = req->trb; + desc_dma = req->trbdma; + + if (ep0->is_in) { + // + // start DMA on EP0 IN + // DMA Descriptor (TRB) setup + // + len = req->length; + if (pcd->ep0state == EP0_IN_STATUS_PHASE) { + if (ep0->three_stage) { + desc_type = TRBCTL_STATUS_3; + } else { + desc_type = TRBCTL_STATUS_2; + } + } else { + desc_type = TRBCTL_CTLDATA_1ST; + } + DwUsb3FillDesc ( + desc, + (UINT64)req->bufdma, + len, + 0, + desc_type, + DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST, + 1 + ); + // + // issue DEPSTRTXFER command to EP0 IN + // + ep0->tri_in = DwUsb3DepStartXfer (EP_IN_IDX (0), desc_dma, 0); + } else { + // + // start DMA on EP0 OUT + // DMA Descriptor (TRB) setup + // + len = ALIGN (req->length, ep0->maxpacket); + if (pcd->ep0state == EP0_OUT_STATUS_PHASE) { + if (ep0->three_stage) { + desc_type = TRBCTL_STATUS_3; + } else { + desc_type = TRBCTL_STATUS_2; + } + } else { + desc_type = TRBCTL_CTLDATA_1ST; + } + DwUsb3FillDesc ( + desc, + (UINT64)req->bufdma, + len, + 0, + desc_type, + DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST, + 1 + ); + // + // issue DEPSTRTXFER command to EP0 OUT + // + ep0->tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), desc_dma, 0); + } +} + +STATIC +INTN +DwUsb3EndPointXStartTransfer ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_ep_t *ep + ) +{ + usb3_pcd_req_t *req = &ep->req; + usb3_dma_desc_t *desc; + UINT64 desc_dma; + UINT32 len; + + // + // get the TRB for this request + // + DwUsb3OsGetTrb (pcd, ep, req); + desc = req->trb; + desc_dma = req->trbdma; + + if (ep->is_in) { + // + // For IN, TRB length is just xfer length + // + len = req->length; + if (ep->xfer_started && !(desc->control & DSCCTL_HWO)) { + DEBUG ((DEBUG_INFO, "[%a] last tx succ, but not in 10s!\n", __func__)); + ep->xfer_started = 0; + } + } else { + // + // For OUT, TRB length must be multiple of maxpacket + // must be power of 2, use cheap AND + // + len = (req->length + ep->maxpacket - 1) & ~(ep->maxpacket - 1); + req->length = len; + } + // + // DMA descriptor setup + // + DwUsb3FillDesc ( + desc, + (UINT64)req->bufdma, + len, + 0, + TRBCTL_NORMAL, + DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST, + 1 + ); + if (ep->is_in) { + // + // start DMA on EPn IN + // + if (ep->xfer_started) { + // + // issue DEPUPDTXFER command to EP + // + DwUsb3DepUpdateXfer (EP_IN_IDX (ep->num), ep->tri_in); + } else { + ep->tri_in = DwUsb3DepStartXfer (EP_IN_IDX (ep->num), desc_dma, 0); + ep->xfer_started = 1; + } + } else { + // + // start DMA on EPn OUT + // + if (ep->xfer_started) { + // + // issue DEPUPDTXFER command to EP + // + DwUsb3DepUpdateXfer (EP_OUT_IDX (ep->num), ep->tri_out); + } else { + ep->tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (ep->num), desc_dma, 0); + ep->xfer_started = 1; + } + } + if (ep->is_in) { + UINT32 count = 0; + // + // wait until send complete + // + while ((desc->control & DSCCTL_HWO) && (count < 1000000)) { + MicroSecondDelay (10); + count++; + } + if (count >= 1000000) { + DEBUG ((DEBUG_INFO, "[%a]: ep%d transfer timeout!\n", __func__, ep->num)); + DEBUG (( + DEBUG_INFO, + "please disconnect then connect USB cable again to recovery!\n" + )); + return -1; + } + ep->xfer_started = 0; + } + return 0; +} + +STATIC +VOID +SetupInStatusPhase ( + IN usb3_pcd_t *pcd, + IN VOID *buf + ) +{ + usb3_pcd_ep_t *ep0 = &pcd->ep0; + + if (pcd->ep0state == EP0_STALL) + return; + + ep0->is_in = 1; + pcd->ep0state = EP0_IN_STATUS_PHASE; + pcd->ep0_req.bufdma = buf; + pcd->ep0_req.length = 0; + pcd->ep0_req.actual = 0; + DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req); +} + +STATIC +VOID +SetupOutStatusPhase ( + IN usb3_pcd_t *pcd, + IN VOID *buf + ) +{ + usb3_pcd_ep_t *ep0 = &pcd->ep0; + + if (pcd->ep0state == EP0_STALL) + return; + + ep0->is_in = 0; + pcd->ep0state = EP0_OUT_STATUS_PHASE; + pcd->ep0_req.bufdma = buf; + pcd->ep0_req.length = 0; + pcd->ep0_req.actual = 0; + DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req); +} + +STATIC +VOID +DwUsb3HandleEndPoint0 ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_req_t *req, + IN UINT32 event + ) +{ + usb3_pcd_ep_t *ep0 = &pcd->ep0; + usb3_dma_desc_t *desc = NULL; + UINT32 byte_count, len; + + switch (pcd->ep0state) { + case EP0_IN_DATA_PHASE: + if (req == NULL) { + req = &pcd->ep0_req; + } + desc = pcd->ep0_in_desc; + + if (desc->control & DSCCTL_HWO) { + goto out; + } + + if (GET_DSCSTS_TRBRSP (desc->status) == TRBRSP_SETUP_PEND) { + // + // start of a new control transfer + // + desc->status = 0; + } + byte_count = req->length - GET_DSCSTS_XFERCNT (desc->status); + req->actual += byte_count; + req->bufdma += byte_count; + + if (req->actual < req->length) { + // + // IN CONTINUE, stall EP0 + // + EndPoint0DoStall (pcd); + } else if (ep0->send_zlp) { + // + // CONTINUE TRANSFER IN ZLP + // + EndPoint0ContinueTransfer (pcd, req); + ep0->send_zlp = 0; + } else { + // + // COMPLETE IN TRANSFER + // + EndPoint0CompleteRequest (pcd, req, desc); + } + break; + case EP0_OUT_DATA_PHASE: + if (req == NULL) { + req = &pcd->ep0_req; + } + desc = pcd->ep0_out_desc; + + if (desc->control & DSCCTL_HWO) { + goto out; + } + + if (GET_DSCSTS_TRBRSP (desc->status) == TRBRSP_SETUP_PEND) { + // + // start of a new control transfer + // + desc->status = 0; + } + len = (req->length + ep0->maxpacket - 1) & ~(ep0->maxpacket - 1); + byte_count = len - GET_DSCSTS_XFERCNT (desc->status); + req->actual += byte_count; + req->bufdma += byte_count; + + if (req->actual < req->length) { + // + // IN CONTINUE, stall EP0 + // + EndPoint0DoStall (pcd); + } else if (ep0->send_zlp) { + // + // CONTINUE TRANSFER IN ZLP + // + EndPoint0ContinueTransfer (pcd, req); + ep0->send_zlp = 0; + } else { + // + // COMPLETE IN TRANSFER + // + EndPoint0CompleteRequest (pcd, req, desc); + } + break; + case EP0_IN_WAIT_NRDY: + if (ep0->is_in) { + SetupInStatusPhase (pcd, gEndPoint0SetupPacket); + } else { + ASSERT (0); + } + break; + case EP0_OUT_WAIT_NRDY: + if (!ep0->is_in) { + SetupOutStatusPhase (pcd, gEndPoint0SetupPacket); + } else { + ASSERT (0); + } + break; + case EP0_IN_STATUS_PHASE: + if (ep0->is_in) { + desc = pcd->ep0_in_desc; + } else { + ASSERT (0); + } + EndPoint0CompleteRequest (pcd, req, desc); + pcd->ep0state = EP0_IDLE; + ep0->stopped = 1; + ep0->is_in = 0; // OUT for next SETUP + // + // prepare for more SETUP packets + // + DwUsb3Ep0OutStart (pcd); + break; + case EP0_OUT_STATUS_PHASE: + if (!ep0->is_in) { + desc = pcd->ep0_out_desc; + } else { + ASSERT (0); + } + EndPoint0CompleteRequest (pcd, req, desc); + pcd->ep0state = EP0_IDLE; + ep0->stopped = 1; + ep0->is_in = 0; // OUT for next SETUP + // + // prepare for more SETUP packets + // + DwUsb3Ep0OutStart (pcd); + break; + case EP0_STALL: + break; + case EP0_IDLE: + break; + default: + DEBUG ((DEBUG_ERROR, "%a: invalid state %d\n", __func__, pcd->ep0state)); + break; + } +out: + return; +} + +STATIC +usb3_pcd_ep_t * +Addr2EndPoint ( + IN usb3_pcd_t *pcd, + IN UINT16 index + ) +{ + UINT32 ep_num; + + ep_num = UE_GET_ADDR (index); + if (ep_num == 0) { + return &pcd->ep0; + } else { + if (UE_GET_DIR (index) == UE_DIR_IN) { + return &pcd->in_ep; + } + return &pcd->out_ep; + } +} + +STATIC +VOID +DwUsb3DoGetStatus ( + IN usb3_pcd_t *pcd + ) +{ + usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req; + UINT8 *status = gEndPoint0StatusBuf; + usb3_pcd_ep_t *ep; + + if (ctrl->wLength != 2) { + EndPoint0DoStall (pcd); + return; + } + + switch (UT_GET_RECIPIENT (ctrl->bmRequestType)) { + case UT_DEVICE: + *status = 0; // bus powered + if (pcd->speed == USB_SPEED_SUPER) { + if (pcd->state == USB3_STATE_CONFIGURED) { + if (MmioRead32 (DCTL) & DCTL_INIT_U1_EN) { + *status |= 1 << 2; + } + if (MmioRead32 (DCTL) & DCTL_INIT_U2_EN) { + *status |= 1 << 3; + } + *status |= (UINT8)(pcd->ltm_enable << 4); + } + } + *(status + 1) = 0; + break; + case UT_INTERFACE: + *status = 0; + *(status + 1) = 0; + break; + case UT_ENDPOINT: + ep = Addr2EndPoint (pcd, ctrl->wIndex); + *status = ep->stopped; + *(status + 1) = 0; + break; + default: + EndPoint0DoStall (pcd); + return; + } + pcd->ep0_req.bufdma = (UINT64 *)status; + pcd->ep0_req.length = 2; + pcd->ep0_req.actual = 0; + DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req); +} + +STATIC +VOID +DoClearHalt ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_ep_t *ep + ) +{ + if (ep->is_in) { + DwUsb3DepClearStall (EP_IN_IDX (ep->num)); + } else { + DwUsb3DepClearStall (EP_OUT_IDX (ep->num)); + } + if (ep->stopped) { + ep->stopped = 0; + } +} + +STATIC +VOID +Usb3PcdEpEnable ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_ep_t *ep + ) +{ + // + // activate the EP + // + ep->stopped = 0; + ep->xfer_started = 0; + ep->ep_desc->control = 0; + ep->ep_desc->status = 0; + // + // set initial data pid. + // + if (ep->type == EPTYPE_BULK) { + ep->data_pid_start = 0; + } + DwUsb3EpActivate (pcd, ep); +} + +STATIC +VOID +DwUsb3DoClearFeature ( + IN usb3_pcd_t *pcd + ) +{ + usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req; + usb3_pcd_ep_t *ep; + + switch (UT_GET_RECIPIENT (ctrl->bmRequestType)) { + case UT_DEVICE: + switch (ctrl->wValue) { + case UF_U1_ENABLE: + if ((pcd->speed != USB_SPEED_SUPER) || + (pcd->state != USB3_STATE_CONFIGURED)) { + EndPoint0DoStall (pcd); + return; + } + MmioAnd32 (DCTL, ~DCTL_INIT_U1_EN); + break; + case UF_U2_ENABLE: + if ((pcd->speed != USB_SPEED_SUPER) || + (pcd->state != USB3_STATE_CONFIGURED)) { + EndPoint0DoStall (pcd); + return; + } + MmioAnd32 (DCTL, ~DCTL_INIT_U2_EN); + break; + case UF_LTM_ENABLE: + if ((pcd->speed != USB_SPEED_SUPER) || + (pcd->state != USB3_STATE_CONFIGURED) || + (ctrl->wIndex != 0)) { + EndPoint0DoStall (pcd); + return; + } + pcd->ltm_enable = 0; + break; + default: + EndPoint0DoStall (pcd); + return; + } + break; + case UT_INTERFACE: + if (ctrl->wValue) { + EndPoint0DoStall (pcd); + return; + } + break; + case UT_ENDPOINT: + ep = Addr2EndPoint (pcd, ctrl->wIndex); + if (ctrl->wValue != UF_ENDPOINT_HALT) { + EndPoint0DoStall (pcd); + return; + } + DoClearHalt (pcd, ep); + break; + default: + DEBUG ((DEBUG_ERROR, "invalid bmRequestType :%d\n", UT_GET_RECIPIENT (ctrl->bmRequestType))); + break; + } + pcd->ep0.is_in = 1; + pcd->ep0state = EP0_IN_WAIT_NRDY; +} + +STATIC +VOID +DwUsb3DoSetFeature ( + IN usb3_pcd_t *pcd + ) +{ + usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req; + usb3_pcd_ep_t *ep; + + switch (UT_GET_RECIPIENT (ctrl->bmRequestType)) { + case UT_DEVICE: + switch (ctrl->wValue) { + case UF_DEVICE_REMOTE_WAKEUP: + break; + case UF_TEST_MODE: + pcd->test_mode_nr = ctrl->wIndex >> 8; + pcd->test_mode = 1; + break; + case UF_U1_ENABLE: + if ((pcd->speed != USB_SPEED_SUPER) || + (pcd->state != USB3_STATE_CONFIGURED)) { + EndPoint0DoStall (pcd); + return; + } + MmioOr32 (DCTL, DCTL_INIT_U1_EN); + break; + case UF_U2_ENABLE: + if ((pcd->speed != USB_SPEED_SUPER) || + (pcd->state != USB3_STATE_CONFIGURED)) { + EndPoint0DoStall (pcd); + return; + } + MmioOr32 (DCTL, DCTL_INIT_U2_EN); + break; + case UF_LTM_ENABLE: + if ((pcd->speed != USB_SPEED_SUPER) || + (pcd->state != USB3_STATE_CONFIGURED) || + (ctrl->wIndex != 0)) { + EndPoint0DoStall (pcd); + return; + } + pcd->ltm_enable = 1; + break; + default: + EndPoint0DoStall (pcd); + return; + } + break; + case UT_INTERFACE: + if (ctrl->wValue) { + EndPoint0DoStall (pcd); + return; + } + break; + case UT_ENDPOINT: + ep = Addr2EndPoint (pcd, ctrl->wIndex); + if (ctrl->wValue != UF_ENDPOINT_HALT) { + EndPoint0DoStall (pcd); + return; + } + ep->stopped = 1; + if (ep->is_in) { + DwUsb3DepClearStall (EP_IN_IDX (ep->num)); + } else { + DwUsb3DepClearStall (EP_OUT_IDX (ep->num)); + } + break; + default: + DEBUG ((DEBUG_ERROR, "invalid bmRequestType %d\n", UT_GET_RECIPIENT (ctrl->bmRequestType))); + break; + } + pcd->ep0.is_in = 1; + pcd->ep0state = EP0_IN_WAIT_NRDY; +} + +STATIC +VOID +DwUsb3DoSetAddress ( + IN usb3_pcd_t *pcd + ) +{ + usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req; + + if (ctrl->bmRequestType == UT_DEVICE) { + SET_DEVADDR (ctrl->wValue); + pcd->ep0.is_in = 1; + pcd->ep0state = EP0_IN_WAIT_NRDY; + if (ctrl->wValue) { + pcd->state = USB3_STATE_ADDRESSED; + } else { + pcd->state = USB3_STATE_DEFAULT; + } + } +} + +STATIC +VOID +DwUsb3DoGetConfig ( + IN usb3_pcd_t *pcd + ) +{ + usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req; + UINT8 *status = gEndPoint0StatusBuf; + + if (ctrl->bmRequestType != (UT_READ | UT_STANDARD | UT_DEVICE)) { + EndPoint0DoStall (pcd); + return; + } + // + // Notify host the current config value + // + *status = pcd->new_config; + pcd->ep0_req.bufdma = (UINT64 *)status; + pcd->ep0_req.length = 1; + pcd->ep0_req.actual = 0; + DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req); +} + +STATIC +VOID +DwUsb3DoSetConfig ( + IN usb3_pcd_t *pcd + ) +{ + usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req; + UINT16 wvalue = ctrl->wValue; + usb3_pcd_ep_t *ep; + + if (ctrl->bmRequestType != (UT_WRITE | UT_STANDARD | UT_DEVICE)) { + EndPoint0DoStall (pcd); + return; + } + + if (!wvalue || (wvalue == CONFIG_VALUE)) { + pcd->new_config = (UINT8)wvalue; + // + // set new configuration + // + if (wvalue) { + // + // activate bulk in endpoint + // + ep = &pcd->in_ep; + Usb3PcdEpEnable (pcd, ep); + // + // activate bulk out endpoint + // + ep = &pcd->out_ep; + Usb3PcdEpEnable (pcd, ep); + pcd->state = USB3_STATE_CONFIGURED; + { + // + // prepare for EP1 OUT + // + usb3_pcd_ep_t *ep = &pcd->out_ep; + usb3_pcd_req_t *req = &ep->req; + + // + // AndroidFast App will free the rx buffer. + // + gRxBuf = AllocatePool (DATA_SIZE); + ASSERT (gRxBuf != NULL); + WriteBackDataCacheRange (gRxBuf, DATA_SIZE); + req->bufdma = (UINT64 *)gRxBuf; + if (mDataBufferSize == 0) { + req->length = CMD_SIZE; + } else if (mDataBufferSize > DATA_SIZE) { + req->length = DATA_SIZE; + mDataBufferSize = mDataBufferSize - DATA_SIZE; + } else if (mDataBufferSize > CMD_SIZE) { + req->length = CMD_SIZE; + mDataBufferSize = mDataBufferSize - CMD_SIZE; + } else { + req->length = mDataBufferSize; + mDataBufferSize = 0; + } + DwUsb3EndPointXStartTransfer (pcd, ep); + } + } else { + pcd->state = USB3_STATE_ADDRESSED; + } + pcd->ep0.is_in = 1; + pcd->ep0state = EP0_IN_WAIT_NRDY; + } else { + EndPoint0DoStall (pcd); + } +} + +STATIC +VOID +DwUsb3DoGetDescriptor ( + IN usb3_pcd_t *pcd + ) +{ + usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req; + UINT8 dt = ctrl->wValue >> 8; + UINT8 index = (UINT8)ctrl->wValue; + UINT16 len = ctrl->wLength; + UINT8 *buf = gEndPoint0StatusBuf; + UINT16 value = 0; + EFI_USB_STRING_DESCRIPTOR *Descriptor = NULL; + + if (ctrl->bmRequestType != (UT_READ | UT_STANDARD | UT_DEVICE)) { + EndPoint0DoStall (pcd); + return; + } + + switch (dt) { + case UDESC_DEVICE: + { + struct usb_device_descriptor *dev = &gDwUsb3DevDesc; + dev->bLength = sizeof (struct usb_device_descriptor); + dev->bDescriptorType = UDESC_DEVICE; + dev->bDeviceClass = 0; + dev->bDeviceSubClass = 0; + dev->bDeviceProtocol = 0; + if (pcd->speed == USB_SPEED_SUPER) { + dev->bcdUSB = 0x300; + // + // 2^9 = 512 + // + dev->bMaxPacketSize0 = 9; + } else { + dev->bcdUSB = 0x0200; + dev->bMaxPacketSize0 = 0x40; + } + dev->idVendor = usb_port_activity_config.idVendor; + dev->idProduct = usb_port_activity_config.idProduct; + dev->bcdDevice = 0x0100; + dev->iManufacturer = STRING_MANUFACTURER; + dev->iProduct = STRING_PRODUCT; + dev->iSerialNumber = STRING_SERIAL; + dev->bNumConfigurations = 1; + value = sizeof (struct usb_device_descriptor); + CopyMem ((void *)buf, (void *)dev, value); + } + break; + case UDESC_DEVICE_QUALIFIER: + { + struct usb_qualifier_descriptor *qual = (struct usb_qualifier_descriptor *)buf; + struct usb_device_descriptor *dev = &gDwUsb3DevDesc; + + qual->bLength = sizeof (*qual); + qual->bDescriptorType = UDESC_DEVICE_QUALIFIER; + qual->bcdUSB = dev->bcdUSB; + qual->bDeviceClass = dev->bDeviceClass; + qual->bDeviceSubClass = dev->bDeviceSubClass; + qual->bDeviceProtocol = dev->bDeviceProtocol; + qual->bMaxPacketSize0 = dev->bMaxPacketSize0; + qual->bNumConfigurations = 1; + qual->bRESERVED = 0; + value = sizeof (struct usb_qualifier_descriptor); + } + break; + + case UDESC_CONFIG: + { + struct usb_config_descriptor *config = (struct usb_config_descriptor *)buf; + + config->bLength = sizeof (*config); + config->bDescriptorType = UDESC_CONFIG; + config->bNumInterfaces = 1; + config->bConfigurationValue = 1; + config->iConfiguration = 0; + config->bmAttributes = USB_CONFIG_ATT_ONE; + + if (pcd->speed == USB_SPEED_SUPER) { + config->bMaxPower = 0x50; + } else { + config->bMaxPower = 0x80; + } + buf += sizeof (*config); + + intf.bInterfaceSubClass = usb_port_activity_config.bInterfaceSubClass; + intf.bInterfaceProtocol = usb_port_activity_config.bInterfaceProtocol; + CopyMem ((void *)buf, (void *)&intf, sizeof (intf)); + buf += sizeof (intf); + + switch (pcd->speed) { + case USB_SPEED_SUPER: + CopyMem (buf, &ss_bulk_in, sizeof (ss_bulk_in)); + buf += sizeof (ss_bulk_in); + CopyMem (buf, &ep_comp, sizeof (ep_comp)); + buf += sizeof (ep_comp); + CopyMem (buf, &ss_bulk_out, sizeof (ss_bulk_out)); + buf += sizeof (ss_bulk_out); + CopyMem (buf, &ep_comp, sizeof (ep_comp)); + + config->wTotalLength = sizeof (*config) + sizeof (intf) + sizeof (ss_bulk_in) + + sizeof (ep_comp) + sizeof (ss_bulk_out) + sizeof (ep_comp); + break; + + default: // HS/FS + { + struct usb_endpoint_descriptor *endp = (struct usb_endpoint_descriptor *)buf; + + CopyMem (buf, &hs_bulk_in, sizeof (hs_bulk_in)); + (endp++)->wMaxPacketSize = pcd->in_ep.maxpacket; + buf += sizeof (hs_bulk_in); + CopyMem (buf, &hs_bulk_out, sizeof (hs_bulk_out)); + endp->wMaxPacketSize = pcd->out_ep.maxpacket; + config->wTotalLength = sizeof (*config) + sizeof (intf) + sizeof (hs_bulk_in) + + sizeof (hs_bulk_out); + break; + } + } + value = config->wTotalLength; + } + break; + + case UDESC_STRING: + { + switch (index) { + case STRING_LANGUAGE: + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf; + ASSERT (Descriptor != NULL); + Descriptor->Length = LANG_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetLang (Descriptor->String, &Descriptor->Length); + value = Descriptor->Length; + break; + case STRING_MANUFACTURER: + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf; + ASSERT (Descriptor != NULL); + Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length); + value = Descriptor->Length; + break; + case STRING_PRODUCT: + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf; + ASSERT (Descriptor != NULL); + Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetProduct (Descriptor->String, &Descriptor->Length); + value = Descriptor->Length; + break; + case STRING_SERIAL: + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)(UINTN)gEndPoint0StatusBuf; + ASSERT (Descriptor != NULL); + Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length); + value = Descriptor->Length; + break; + default: + EndPoint0DoStall (pcd); + break; + } + } + break; + + case UDESC_BOS: + if (pcd->speed != USB_SPEED_SUPER) { + EndPoint0DoStall (pcd); + return; + } + value = bos.wTotalLength; + CopyMem (buf, &bos, sizeof (bos)); + buf += sizeof (bos); + CopyMem (buf, &cap1, sizeof (cap1)); + buf += sizeof (cap1); + CopyMem (buf, &cap2, sizeof (cap2)); + buf += sizeof (cap2); + CopyMem (buf, &cap3, sizeof (cap3)); + break; + default: + EndPoint0DoStall (pcd); + return; + } + pcd->ep0_req.bufdma = (UINT64 *)gEndPoint0StatusBuf; + pcd->ep0_req.length = value < len ? value : len; + pcd->ep0_req.actual = 0; + DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req); +} + +STATIC +VOID +DwUsb3DoSetup ( + IN usb3_pcd_t *pcd + ) +{ + usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req; + usb3_pcd_ep_t *ep0 = &pcd->ep0; + UINT16 wLength; + + wLength = ctrl->wLength; + ep0->stopped = 0; + ep0->three_stage = 1; + if (ctrl->bmRequestType & UE_DIR_IN) { + ep0->is_in = 1; + pcd->ep0state = EP0_IN_DATA_PHASE; + } else { + ep0->is_in = 0; + pcd->ep0state = EP0_OUT_DATA_PHASE; + } + + if (wLength == 0) { + ep0->is_in = 1; + pcd->ep0state = EP0_IN_WAIT_NRDY; + ep0->three_stage = 0; + } + if (UT_GET_TYPE (ctrl->bmRequestType) != UT_STANDARD) { + EndPoint0DoStall (pcd); + return; + } + + switch (ctrl->bRequest) { + case UR_GET_STATUS: + DwUsb3DoGetStatus (pcd); + break; + case UR_CLEAR_FEATURE: + DwUsb3DoClearFeature (pcd); + break; + case UR_SET_FEATURE: + DwUsb3DoSetFeature (pcd); + break; + case UR_SET_ADDRESS: + DwUsb3DoSetAddress (pcd); + break; + case UR_SET_CONFIG: + DwUsb3DoSetConfig (pcd); + MmioOr32 (DCTL, DCTL_ACCEPT_U1_EN); + MmioOr32 (DCTL, DCTL_ACCEPT_U2_EN); + DEBUG ((DEBUG_INFO, "enum done")); + pcd->ltm_enable = 0; + break; + case UR_GET_CONFIG: + DwUsb3DoGetConfig (pcd); + break; + case UR_GET_DESCRIPTOR: + DwUsb3DoGetDescriptor (pcd); + break; + case UR_SET_SEL: + // + // for now this is a no-op + // + pcd->ep0_req.bufdma = (UINT64 *)gEndPoint0StatusBuf; + pcd->ep0_req.length = USB3_STATUS_BUF_SIZE; + pcd->ep0_req.actual = 0; + ep0->send_zlp = 0; + DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req); + break; + default: + EndPoint0DoStall (pcd); + break; + } +} + +STATIC +VOID +DwUsb3OsHandleEndPoint0 ( + IN usb3_pcd_t *pcd, + IN UINT32 event + ) +{ + if (pcd->ep0state == EP0_IDLE) { + DwUsb3DoSetup (pcd); + } else { + DwUsb3HandleEndPoint0 (pcd, NULL, event); + } +} + +STATIC +VOID +DwUsb3RequestDone ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_ep_t *ep, + IN usb3_pcd_req_t *req, + IN UINTN status + ) +{ + if (ep != &pcd->ep0) { + req->trb = NULL; + } + if (req->complete) { + req->complete (req->actual, status); + } else { + if (!ep->is_in) { + ASSERT (req->actual <= req->length); + InvalidateDataCacheRange (gRxBuf, req->actual); + mDataReceivedCallback (req->actual, gRxBuf); + } + } + req->actual = 0; +} + +STATIC +VOID +DwUsb3EndPointcompleteRequest ( + IN usb3_pcd_t *pcd, + IN usb3_pcd_ep_t *ep, + IN UINT32 event + ) +{ + usb3_pcd_req_t *req = &ep->req; + usb3_dma_desc_t *desc = req->trb; + UINT32 byte_count; + + ep->send_zlp = 0; + if (!desc) { + return; + } + + if (desc->control & DSCCTL_HWO) { + return; + } + + if (ep->is_in) { + // + // IN ep + // + if (GET_DSCSTS_XFERCNT (desc->status) == 0) { + req->actual += req->length; + } + // + // reset IN tri + // + ep->tri_in = 0; + // + // complete the IN request + // + DwUsb3RequestDone (pcd, ep, req, 0); + } else { + // + // OUT ep + // + byte_count = req->length - GET_DSCSTS_XFERCNT (desc->status); + req->actual += byte_count; + // + //req->bufdma += byte_count; + // reset OUT tri + // + ep->tri_out = 0; + // + // OUT transfer complete or not + // complete the OUT request + // + DwUsb3RequestDone (pcd, ep, req, 0); + { + // + // prepare for EP1 OUT + // + usb3_pcd_ep_t *ep = &pcd->out_ep; + usb3_pcd_req_t *req = &ep->req; + + ZeroMem (req, sizeof (usb3_pcd_req_t)); + gRxBuf = AllocatePool (DATA_SIZE); + ASSERT (gRxBuf != NULL); + WriteBackDataCacheRange (gRxBuf, DATA_SIZE); + req->bufdma = (UINT64 *)gRxBuf; + if (mDataBufferSize == 0) { + req->length = CMD_SIZE; + } else if (mDataBufferSize > DATA_SIZE) { + req->length = DATA_SIZE; + mDataBufferSize = mDataBufferSize - DATA_SIZE; + } else if (mDataBufferSize > CMD_SIZE) { + req->length = CMD_SIZE; + mDataBufferSize = mDataBufferSize - CMD_SIZE; + } else { + req->length = mDataBufferSize; + mDataBufferSize = 0; + } + DwUsb3EndPointXStartTransfer (pcd, ep); + } + } +} + +STATIC +VOID +DwUsb3HandleEndPointInterrupt ( + IN usb3_pcd_t *pcd, + IN UINTN PhySep, + IN UINT32 event + ) +{ + usb3_pcd_ep_t *ep; + UINT32 epnum, is_in; + + // + // Physical Out EPs are even, physical In EPs are odd + // + is_in = (UINT32)PhySep & 1; + epnum = ((UINT32)PhySep >> 1) & 0xF; + + // + // Get the EP pointer + // + if (is_in) { + ep = DwUsb3GetInEndPoint (pcd, epnum); + } else { + ep = DwUsb3GetOutEndPoint (pcd, epnum); + } + + switch (event & GEVNT_DEPEVT_INTTYPE_MASK) { + case GEVNT_DEPEVT_INTTYPE_XFER_CMPL: + ep->xfer_started = 0; + // + // complete the transfer + // + if (epnum == 0) { + DwUsb3OsHandleEndPoint0 (pcd, event); + } else { + DwUsb3EndPointcompleteRequest (pcd, ep, event); + } + break; + case GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG: + break; + case GEVNT_DEPEVT_INTTYPE_XFER_NRDY: + if (epnum == 0) { + switch (pcd->ep0state) { + case EP0_IN_WAIT_NRDY: + if (is_in) { + DwUsb3OsHandleEndPoint0 (pcd, event); + } else { + } + break; + case EP0_OUT_WAIT_NRDY: + if (!is_in) { + DwUsb3OsHandleEndPoint0 (pcd, event); + } else { + } + break; + default: + break; + } + } else { + } + break; + default: + DEBUG (( + DEBUG_ERROR, + "invalid event %d\n", + event & GEVNT_DEPEVT_INTTYPE_MASK + )); + break; + } +} + +STATIC +UINTN +DwUsb3HandleEvent ( + VOID + ) +{ + usb3_pcd_t *pcd = &gPcd; + UINT32 Count, Index, Event, Intr; + UINT32 PhySep; + + Count = GET_EVENTBUF_COUNT (); + // + // reset event buffer when it's full + // + if ((GEVNTCOUNT_EVNTCOUNT (Count) == GEVNTCOUNT_EVNTCOUNT_MASK) || + (Count >= DWUSB3_EVENT_BUF_SIZE * sizeof (UINT32))) { + UPDATE_EVENTBUF_COUNT (Count); + Count = 0; + } + + for (Index = 0; Index < Count; Index += sizeof (UINT32)) { + Event = DwUsb3GetEventBufEvent (DWUSB3_EVENT_BUF_SIZE << 2); + UPDATE_EVENTBUF_COUNT (sizeof (UINT32)); + if (Event == 0) { + // + // ignore null events + // + continue; + } + if (Event & GEVNT_NON_EP) { + Intr = Event & GEVNT_INTTYPE_MASK; + if (Intr == GEVNT_INTTYPE (EVENT_DEV_INT)) { + DwUsb3HandleDeviceInterrupt (pcd, Event); + } + } else { + PhySep = (Event & GEVNT_DEPEVT_EPNUM_MASK) >> GEVNT_DEPEVT_EPNUM_SHIFT; + DwUsb3HandleEndPointInterrupt (pcd, PhySep, Event); + } + } + return 0; +} + +STATIC +VOID +DwUsb3Poll ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + if (DwUsb3HandleEvent ()) { + DEBUG ((DEBUG_ERROR, "error: exit from usb_poll\n")); + return; + } +} + +EFI_STATUS +EFIAPI +DwUsb3Start ( + IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor, + IN VOID **Descriptors, + IN USB_DEVICE_RX_CALLBACK RxCallback, + IN USB_DEVICE_TX_CALLBACK TxCallback + ) +{ + EFI_STATUS Status; + EFI_EVENT TimerEvent; + + Status = DmaAllocateBuffer ( + EfiBootServicesData, + EFI_SIZE_TO_PAGES (DWUSB3_EVENT_BUF_SIZE << 2), + (VOID *)&gEventBuf + ); + if (EFI_ERROR (Status)) { + return Status; + } + if (gEventBuf == NULL) { + return EFI_OUT_OF_RESOURCES; + } + ZeroMem (gEventBuf, EFI_SIZE_TO_PAGES (DWUSB3_EVENT_BUF_SIZE << 2)); + gEventPtr = gEventBuf; + DriverInit (); + DwUsb3Init (); + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + DwUsb3Poll, + NULL, + &TimerEvent + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->SetTimer ( + TimerEvent, + TimerPeriodic, + DW_INTERRUPT_POLL_PERIOD + ); + ASSERT_EFI_ERROR (Status); + mDataReceivedCallback = RxCallback; + return Status; +} + +EFI_STATUS +DwUsb3Send ( + IN UINT8 EndpointIndex, + IN UINTN Size, + IN CONST VOID *Buffer + ) +{ + usb3_pcd_t *pcd = &gPcd; + usb3_pcd_ep_t *ep = &pcd->in_ep; + usb3_pcd_req_t *req = &ep->req; + + WriteBackDataCacheRange ((VOID *)Buffer, Size); + req->bufdma = (UINT64 *)Buffer; + req->length = Size; + DwUsb3EndPointXStartTransfer (pcd, ep); + return EFI_SUCCESS; +} + +USB_DEVICE_PROTOCOL mUsbDevice = { + DwUsb3Start, + DwUsb3Send +}; + +EFI_STATUS +EFIAPI +DwUsb3EntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DmaAllocateBuffer ( + EfiBootServicesData, + EFI_SIZE_TO_PAGES (sizeof (usb_setup_pkt_t) * 5), + (VOID *)&gEndPoint0SetupPacket + ); + if (EFI_ERROR (Status)) { + return Status; + } + Status = DmaAllocateBuffer ( + EfiBootServicesData, + EFI_SIZE_TO_PAGES (USB3_STATUS_BUF_SIZE * sizeof (UINT8)), + (VOID *)&gEndPoint0StatusBuf + ); + if (EFI_ERROR (Status)) { + goto Out; + } + Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb); + if (EFI_ERROR (Status)) { + goto OutProtocol; + } + + Status = DwUsb->PhyInit(USB_DEVICE_MODE); + if (EFI_ERROR (Status)) { + goto OutProtocol; + } + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gUsbDeviceProtocolGuid, + EFI_NATIVE_INTERFACE, + &mUsbDevice + ); + if (EFI_ERROR (Status)) { + goto OutProtocol; + } + return Status; + +OutProtocol: + DmaFreeBuffer ( + EFI_SIZE_TO_PAGES (USB3_STATUS_BUF_SIZE * sizeof (UINT8)), + (VOID *)gEndPoint0StatusBuf + ); +Out: + DmaFreeBuffer ( + EFI_SIZE_TO_PAGES (sizeof (usb_setup_pkt_t) * 5), + (VOID *)gEndPoint0SetupPacket + ); + return Status; +}
Add Designware USB 3.0 device driver. It's focus on USB device functionality, not USB Host functionality. The USB driver is mainly used for Android Fastboot application. Cc: Leif Lindholm <leif.lindholm@linaro.org> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> --- EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.dec | 44 + EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.inf | 52 + EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.h | 632 +++++ EmbeddedPkg/Drivers/DwUsb3Dxe/DwUsb3Dxe.c | 2434 ++++++++++++++++++++ 4 files changed, 3162 insertions(+) -- 2.7.4 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel