From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 00138819DC for ; Sat, 21 Jan 2017 19:12:50 -0800 (PST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga102.fm.intel.com with ESMTP; 21 Jan 2017 19:12:48 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,267,1477983600"; d="dat'59?scan'59,208,59";a="1085798016" Received: from fmsmsx105.amr.corp.intel.com ([10.18.124.203]) by orsmga001.jf.intel.com with ESMTP; 21 Jan 2017 19:12:45 -0800 Received: from fmsmsx120.amr.corp.intel.com (10.18.124.208) by FMSMSX105.amr.corp.intel.com (10.18.124.203) with Microsoft SMTP Server (TLS) id 14.3.248.2; Sat, 21 Jan 2017 19:12:45 -0800 Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by fmsmsx120.amr.corp.intel.com (10.18.124.208) with Microsoft SMTP Server (TLS) id 14.3.248.2; Sat, 21 Jan 2017 19:12:42 -0800 Received: from shsmsx103.ccr.corp.intel.com ([169.254.4.20]) by SHSMSX104.ccr.corp.intel.com ([10.239.4.70]) with mapi id 14.03.0248.002; Sun, 22 Jan 2017 11:12:39 +0800 From: "Guo, Mang" To: "edk2-devel@lists.01.org" CC: "Wei, David" , "Guo, Mang" Thread-Topic: [Patch][edk2-platforms/devel-MinnowBoard3] Add USB peripheral mode Thread-Index: AdJ0XWHyjqkQweVvRvWzY/alut0s/w== Date: Sun, 22 Jan 2017 03:12:37 +0000 Message-ID: <22D2C85ED001C54AA20BFE3B0E4751D1524D4ECF@SHSMSX103.ccr.corp.intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: <22D2C85ED001C54AA20BFE3B0E4751D1524D4ECF@SHSMSX103.ccr.corp.intel.com> x-originating-ip: [10.239.127.40] MIME-Version: 1.0 X-Content-Filtered-By: Mailman/MimeDel 2.1.21 Subject: [Patch][edk2-platforms/devel-MinnowBoard3] Add USB peripheral mode X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 22 Jan 2017 03:12:51 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../Common/Features/UsbDeviceDxe/ComponentName.c | 305 ++ .../Common/Features/UsbDeviceDxe/UsbDeviceDxe.c | 395 ++ .../Common/Features/UsbDeviceDxe/UsbDeviceDxe.h | 159 + .../Common/Features/UsbDeviceDxe/UsbDeviceDxe.inf | 74 + .../Common/Features/UsbDeviceDxe/UsbDeviceMode.c | 1489 ++++++++ .../Common/Features/UsbDeviceDxe/UsbDeviceMode.h | 39 + .../Common/Features/UsbDeviceDxe/UsbFuncIo.c | 2219 +++++++++++ .../Common/Features/UsbDeviceDxe/UsbFuncIo.h | 234 ++ .../Common/Features/UsbDeviceDxe/UsbIoNode.c | 177 + .../Common/Features/UsbDeviceDxe/UsbIoNode.h | 90 + .../Common/Features/UsbDeviceDxe/XdciCommon.h | 156 + .../Common/Features/UsbDeviceDxe/XdciDWC.c | 4033 ++++++++++++++++= ++++ .../Common/Features/UsbDeviceDxe/XdciDWC.h | 741 ++++ .../Common/Features/UsbDeviceDxe/XdciDevice.c | 695 ++++ .../Common/Features/UsbDeviceDxe/XdciDevice.h | 184 + .../Common/Features/UsbDeviceDxe/XdciInterface.h | 241 ++ .../Common/Features/UsbDeviceDxe/XdciTable.c | 55 + .../Common/Features/UsbDeviceDxe/XdciUtility.c | 148 + .../Common/Features/UsbDeviceDxe/XdciUtility.h | 62 + .../Common/Include/Protocol/EfiUsbFnIo.h | 430 +++ .../Include/Protocol/UsbDeviceModeProtocol.h | 104 + .../Common/Library/PmicLib/PmicDummy.c | 142 + .../Common/Library/PmicLib/PmicLibNull.c | 658 ++++ .../Common/Library/PmicLib/PmicLibNull.inf | 44 + .../Common/Library/PmicLib/PmicPrivate.h | 82 + .../PlatformSetupDxe/SouthClusterConfig.vfi | 6 +- .../BroxtonPlatformPkg/PlatformDsc/Components.dsc | 2 + .../PlatformDsc/LibraryClasses.dsc | 4 +- Platform/BroxtonPlatformPkg/PlatformPkg.fdf | 2 + .../SouthCluster/Include/ScRegs/RegsUsb.h | 10 +- 30 files changed, 12975 insertions(+), 5 deletions(-) create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/ComponentName.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/UsbDeviceDxe.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/UsbDeviceDxe.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/UsbDeviceDxe.inf create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/UsbDeviceMode.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/UsbDeviceMode.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/UsbFuncIo.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/UsbFuncIo.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/UsbIoNode.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/UsbIoNode.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/XdciCommon.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/XdciDWC.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/XdciDWC.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/XdciDevice.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/XdciDevice.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/XdciInterface.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/XdciTable.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/XdciUtility.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDx= e/XdciUtility.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Include/Protocol/Efi= UsbFnIo.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Include/Protocol/Usb= DeviceModeProtocol.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Library/PmicLib/Pmic= Dummy.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Library/PmicLib/Pmic= LibNull.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Library/PmicLib/Pmic= LibNull.inf create mode 100644 Platform/BroxtonPlatformPkg/Common/Library/PmicLib/Pmic= Private.h diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/Compo= nentName.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/Compo= nentName.c new file mode 100644 index 0000000..9495806 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/ComponentNam= e.c @@ -0,0 +1,305 @@ +/** @file + Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include +#include + + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f a + Unicode string. If the driver specified by This has a user readable name= in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by + This and the language specified by Languag= e was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handl= e + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is th= e + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format= . + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL mUsbDeviceDxeCo= mponentName =3D { + UsbDeviceDxeGetDriverName, + UsbDeviceDxeGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL mUsbDeviceDxeCo= mponentName2 =3D { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) UsbDeviceDxeGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) UsbDeviceDxeGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUsbDeviceDxeDriver= NameTable[] =3D { + { "eng;en", L"Usb Device Driver" }, + { NULL , NULL } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f a + Unicode string. If the driver specified by This has a user readable name= in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by + This and the language specified by Languag= e was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mUsbDeviceDxeDriverNameTable, + DriverName, + (BOOLEAN)(This =3D=3D &mUsbDeviceDxeComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handl= e + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII strin= g + array indicating the language. This is th= e + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format= . + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE= . + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDe= viceDxe.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDev= iceDxe.c new file mode 100644 index 0000000..03bf27d --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe= .c @@ -0,0 +1,395 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "UsbDeviceDxe.h" +#include + +EFI_DRIVER_BINDING_PROTOCOL mUsbDeviceDxeDriverBinding =3D { + UsbDeviceDxeDriverSupported, + UsbDeviceDxeDriverStart, + UsbDeviceDxeDriverStop, + 0x1, + NULL, + NULL +}; + + + +VOID +EFIAPI +PlatformSpecificInit ( + VOID + ) +{ + UINTN XhciPciMmBase; + EFI_PHYSICAL_ADDRESS XhciMemBaseAddress; + + XhciPciMmBase =3D MmPciAddress ( + 0, + 0, + PCI_DEVICE_NUMBER_XHCI, + PCI_FUNCTION_NUMBER_XHCI, + 0 + ); + + + XhciMemBaseAddress =3D MmioRead32 ((UINTN) (XhciPciMmBase + R_XHCI_MEM_B= ASE)) & B_XHCI_MEM_BASE_BA; + DEBUG ((DEBUG_INFO, "XhciPciMmBase=3D%x, XhciMemBaseAddress=3D%x\n", Xhc= iPciMmBase, XhciMemBaseAddress)); + + MmioWrite32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_ROLE_CFG0), 0x= 1310800); + + PmicUSBSwitchControl (TRUE);//conduction USB switch. + return; +} + + +VOID +EFIAPI +UsbDeviceDxeExitBootService ( + EFI_EVENT Event, + VOID *Context + ) +{ + USB_XDCI_DEV_CONTEXT *UsbXdciDevContext; + + UsbXdciDevContext =3D (USB_XDCI_DEV_CONTEXT *) Context; + DEBUG ((EFI_D_INFO, "UsbDeviceDxeExitBootService enter\n")); + + if (UsbXdciDevContext->XdciPollTimer !=3D NULL) { + gBS->SetTimer (UsbXdciDevContext->XdciPollTimer, TimerCancel, 0); + gBS->CloseEvent (UsbXdciDevContext->XdciPollTimer); + UsbXdciDevContext->XdciPollTimer =3D NULL; + } + + return; +} + +/** + The USB bus driver entry pointer. + + @param ImageHandle The driver image handle. + @param SystemTable The system table. + + @return EFI_SUCCESS The component name protocol is installed. + @return Others Failed to init the usb driver. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &mUsbDeviceDxeDriverBinding, + ImageHandle, + &mUsbDeviceDxeComponentName, + &mUsbDeviceDxeComponentName2 + ); +} + +/** + Check whether USB bus driver support this device. + + @param This The USB bus driver binding protocol. + @param Controller The controller handle to check. + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS The bus supports this controller. + @retval EFI_UNSUPPORTED This device isn't supported. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + USB_CLASSC UsbClassCReg; + + + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status =3D PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_CLASSCODE_OFFSET, + sizeof (USB_CLASSC) / sizeof (UINT8), + &UsbClassCReg + ); + + if (EFI_ERROR (Status)) { + Status =3D EFI_UNSUPPORTED; + goto ON_EXIT; + } + + // + // Test whether the controller belongs to USB device type + // + // 0x0C03FE / 0x0C0380 + // + if ((UsbClassCReg.BaseCode !=3D PCI_CLASS_SERIAL) || + (UsbClassCReg.SubClassCode !=3D PCI_CLASS_SERIAL_USB) || + ((UsbClassCReg.ProgInterface !=3D PCI_IF_USBDEV) && (UsbClassCReg.Pr= ogInterface !=3D 0x80))) { + Status =3D EFI_UNSUPPORTED; + } + +ON_EXIT: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + + +/** + Start to process the controller. + + @param This The USB bus driver binding instance. + @param Controller The controller to check. + @param RemainingDevicePath The remaining device patch. + + @retval EFI_SUCCESS The controller is controlled by the usb b= us. + @retval EFI_ALREADY_STARTED The controller is already controlled by t= he usb + bus. + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbXdciDevContext; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_EVENT ExitBootServicesEvent; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbFunIoEntryPoint - Entry\n")); + + UsbXdciDevContext =3D NULL; + + // + // Provide protocol interface + // + // + // Get the PCI I/O Protocol on PciHandle + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + UsbXdciDevContext =3D AllocateZeroPool (sizeof (USB_XDCI_DEV_CONTEXT)); + if (UsbXdciDevContext =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + // + // Initialize the driver context + // + UsbXdciDevContext->StartUpController =3D FALSE; + UsbXdciDevContext->XdciHandle =3D Controller; + UsbXdciDevContext->FirstNodePtr =3D NULL; + UsbXdciDevContext->Signature =3D EFI_USB_DEV_SIGNATURE; + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + R_OTG_BAR0, + 1, + &UsbXdciDevContext->XdciMmioBarAddr + ); + + UsbXdciDevContext->XdciMmioBarAddr &=3D B_OTG_BAR0_BA; + DEBUG ((USB_FUIO_DEBUG_INFO, "USB DEV mode IO addr 0x%08x\n", UsbXdciDev= Context->XdciMmioBarAddr)); + + CopyMem ( + &(UsbXdciDevContext->UsbFunIoProtocol), + &mUsbFunIoProtocol, + sizeof (EFI_USBFN_IO_PROTOCOL) + ); + + CopyMem ( + &(UsbXdciDevContext->UsbDevModeProtocol), + &mUsbDeviceModeProtocol, + sizeof (EFI_USB_DEVICE_MODE_PROTOCOL) + ); + + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + UsbDeviceDxeExitBootService, + UsbXdciDevContext, + &gEfiEventExitBootServicesGuid, + &ExitBootServicesEvent + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &UsbXdciDevContext->XdciHandle, + &gEfiUsbFnIoProtocolGuid, + &UsbXdciDevContext->UsbFunIoProtocol, + &gEfiUsbDeviceModeProtocolGuid, + &UsbXdciDevContext->UsbDevModeProtocol, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((USB_FUIO_DEBUG_ERROR, "ERROR - Failed to install upper protoco= l, Status: %r\n", Status)); + goto ErrorExit; + } + + DEBUG ((USB_FUIO_DEBUG_LOAD, "Done - install upper protocol complete\n")= ); + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbFunIoEntryPoint - Exit\n")); + return Status; + +ErrorExit: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if (UsbXdciDevContext !=3D NULL) { + if (UsbXdciDevContext->XdciPollTimer !=3D NULL) { + gBS->CloseEvent (UsbXdciDevContext->XdciPollTimer); + UsbXdciDevContext->XdciPollTimer =3D NULL; + } + FreePool (UsbXdciDevContext); + } + + DEBUG ((USB_FUIO_DEBUG_ERROR, "ERROR - UsbFunIoEntryPoint - Exit\n")); + return Status; +} + +/** + Stop handle the controller by this USB bus driver. + + @param This The USB bus driver binding protocol. + @param Controller The controller to release. + @param NumberOfChildren The child of USB bus that opened controll= er + BY_CHILD. + @param ChildHandleBuffer The array of child handle. + + @retval EFI_SUCCESS The controller or children are stopped. + @retval EFI_DEVICE_ERROR Failed to stop the driver. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_USBFN_IO_PROTOCOL *UsbFunIoProtocol; + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbXdciDevContext; + + + // + // Locate USB_BUS for the current host controller + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiUsbFnIoProtocolGuid, + &UsbFunIoProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + + if (EFI_ERROR (Status)) { + return Status; + } + + UsbXdciDevContext =3D USBFUIO_CONTEXT_FROM_PROTOCOL (UsbFunIoProtocol); + + // + // free pool + // + while (UsbXdciDevContext->FirstNodePtr !=3D NULL) { + RemoveNode (UsbFunIoProtocol, UsbXdciDevContext->FirstNodePtr); + } + + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + UsbXdciDevContext->XdciHandle, + &gEfiUsbFnIoProtocolGuid, + &UsbXdciDevContext->UsbFunIoProtocol, + &gEfiUsbDeviceModeProtocolGuid, + &UsbXdciDevContext->UsbDevModeProtocol, + NULL + ); + + if (UsbXdciDevContext->StartUpController =3D=3D TRUE) { + Status =3D StopController (UsbFunIoProtocol); + DEBUG ((USB_FUIO_DEBUG_INFO, "USB DEV mode STOP UsbFnDeInitDevice %r\n= ", Status)); + } + + if (UsbXdciDevContext->XdciPollTimer !=3D NULL) { + gBS->SetTimer (UsbXdciDevContext->XdciPollTimer, TimerCancel, 0); + gBS->CloseEvent (UsbXdciDevContext->XdciPollTimer); + UsbXdciDevContext->XdciPollTimer =3D NULL; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + FreePool (UsbXdciDevContext); + return EFI_SUCCESS; +} + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDe= viceDxe.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDev= iceDxe.h new file mode 100644 index 0000000..e300fbf --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe= .h @@ -0,0 +1,159 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef __USB_DEVICE_DXE_H__ +#define __USB_DEVICE_DXE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "UsbFuncIo.h" +#include "UsbDeviceMode.h" + + +#define PCI_IF_USBDEV 0xFE + +#define EFI_USB_DEV_SIGNATURE 0x55534244 //"USBD" +#define USBFUIO_CONTEXT_FROM_PROTOCOL(a) CR (a, USB_XDCI_DEV_CONTEXT, Us= bFunIoProtocol, EFI_USB_DEV_SIGNATURE) +#define USBUSBD_CONTEXT_FROM_PROTOCOL(a) CR (a, USB_XDCI_DEV_CONTEXT, Us= bDevModeProtocol, EFI_USB_DEV_SIGNATURE) + + +typedef struct _USB_FUIO_EVENT_NODE USB_FUIO_EVENT_NODE; + +#pragma pack(1) +struct _USB_FUIO_EVENT_NODE{ + EFI_USBFN_MESSAGE Message; + UINTN PayloadSize; + EFI_USBFN_MESSAGE_PAYLOAD Payload; + USB_FUIO_EVENT_NODE *Nextptr; +}; + +typedef struct { + UINTN Signature; + UINTN XdciMmioBarAddr; + EFI_HANDLE XdciHandle; + // + // Timer to handle EndPoint event periodically. + // + EFI_EVENT XdciPollTimer; + EFI_USB_DEVICE_MODE_PROTOCOL UsbDevModeProtocol; + EFI_USBFN_IO_PROTOCOL UsbFunIoProtocol; + + // + // Structure members used by UsbFunIoProtocol. + // + USB_MEM_NODE *FirstNodePtr; + EFI_USB_DEVICE_INFO *DevInfoPtr; + EFI_USB_CONFIG_INFO IndexPtrConfig; + EFI_USB_INTERFACE_INFO IndexPtrInteface; + USB_DEVICE_ENDPOINT_INFO IndexPtrInEp; + USB_DEVICE_ENDPOINT_INFO IndexPtrOutEp; + XDCI_CORE_HANDLE *XdciDrvIfHandle; + USB_DEV_CORE *DrvCore; + UINT16 VendorId; + UINT16 DeviceId; + USBD_EP_XFER_REC EndPointXferRec[DWC_XDCI_MAX_ENDPOINTS]; + BOOLEAN StartUpController; + BOOLEAN DevReConnect; + BOOLEAN DevResetFlag; + EFI_EVENT TimerEvent; + USB_FUIO_EVENT_NODE *EventNodePtr; + // + // Following structure members are used by UsbDevModeProtocol. + // + +} USB_XDCI_DEV_CONTEXT; +#pragma pack() + + + +/** + Check whether USB bus driver support this device. + + @param This The USB bus driver binding protocol. + @param Controller The controller handle to check. + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS The bus supports this controller. + @retval EFI_UNSUPPORTED This device isn't supported. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Start to process the controller. + + @param This The USB bus driver binding instance. + @param Controller The controller to check. + @param RemainingDevicePath The remaining device patch. + + @retval EFI_SUCCESS The controller is controlled by the usb b= us. + @retval EFI_ALREADY_STARTED The controller is already controlled by t= he usb + bus. + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop handle the controller by this USB bus driver. + + @param This The USB bus driver binding protocol. + @param Controller The controller to release. + @param NumberOfChildren The child of USB bus that opened controll= er + BY_CHILD. + @param ChildHandleBuffer The array of child handle. + + @retval EFI_SUCCESS The controller or children are stopped. + @retval EFI_DEVICE_ERROR Failed to stop the driver. + +**/ +EFI_STATUS +EFIAPI +UsbDeviceDxeDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +VOID +EFIAPI +PlatformSpecificInit ( + VOID + ); + +extern EFI_COMPONENT_NAME_PROTOCOL mUsbDeviceDxeComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL mUsbDeviceDxeComponentName2; + +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDe= viceDxe.inf b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbD= eviceDxe.inf new file mode 100644 index 0000000..46c499a --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe= .inf @@ -0,0 +1,74 @@ +## @file +# +# Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e 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 IM= PLIED. +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D UsbDeviceDxe + FILE_GUID =3D 42CF2D4A-78B4-4B80-80F9-96A83A630D70 + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D UsbDeviceDxeEntryPoint + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources.common] + UsbDeviceDxe.c + UsbFuncIo.c + UsbIoNode.c + ComponentName.c + UsbDeviceMode.c + XdciDevice.c + XdciDWC.c + XdciTable.c + XdciUtility.c + +[Packages] + MdePkg/MdePkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + BroxtonPlatformPkg/PlatformPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + DevicePathLib + MemoryAllocationLib + TimerLib + PcdLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + PmicLib + +[Protocols] + gEfiUsbDeviceModeProtocolGuid + gEfiUsbFnIoProtocolGuid + gEfiPciIoProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + +[Guids] + gEfiEventExitBootServicesGuid + +#[BuildOptions] +# MSFT:*_*_*_CC_FLAGS =3D /D SUPPORT_SUPER_SPEED +# GCC:*_*_*_CC_FLAGS =3D -DSUPPORT_SUPER_SPEED + +[Depex] + TRUE + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDe= viceMode.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDe= viceMode.c new file mode 100644 index 0000000..d0358b9 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceMod= e.c @@ -0,0 +1,1489 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include "XdciUtility.h" +#include "UsbDeviceMode.h" +#include "UsbDeviceDxe.h" + +// +// Global USBD driver object. This is the main private driver object +// that contains all data needed for this driver to operate. +// +USB_DEVICE_DRIVER_OBJ mDrvObj; + +// +// Global data IO transaction request object +// +USB_DEVICE_IO_REQ mCtrlIoReq =3D { + // + // IO information containing the Buffer and data size + // + { + NULL, + 0, + }, + // + // Note: This object is used for Control Ep transfers only + // therefore the endpoint info must always be NULL + // + { + NULL, + NULL, + } +}; + +// +// global flag to signal device event processing loop to run/stop +// +BOOLEAN mXdciRun =3D FALSE; + +STATIC VOID +XhciSwitchSwid(BOOLEAN enable) +{ + UINTN XhciPciMmBase; + EFI_PHYSICAL_ADDRESS XhciMemBaseAddress; + UINT32 DualRoleCfg0; + UINT32 DualRoleCfg1; + + XhciPciMmBase =3D MmPciAddress (0, 0, PCI_DEVICE_NUMBER_XHCI, PCI_FUNCTI= ON_NUMBER_XHCI, 0); + XhciMemBaseAddress =3D MmioRead32 ((UINTN) (XhciPciMmBase + R_XHCI_MEM_B= ASE)) & B_XHCI_MEM_BASE_BA; + DEBUG ((DEBUG_INFO, "XhciPciMmBase=3D%x, XhciMemBaseAddress=3D%x\n", Xhc= iPciMmBase, XhciMemBaseAddress)); + + DualRoleCfg0 =3D MmioRead32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUA= L_ROLE_CFG0)); + if (enable) { + DualRoleCfg0 =3D DualRoleCfg0 | (1 << 24) | (1 << 21) | (1 << 20); + DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Set SW ID : 0x%x \n", DualRoleCfg0= )); + } + else { + DualRoleCfg0 =3D DualRoleCfg0 & ~(1 << 24) & ~(1 << 21) & ~(1 << 20); + DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Clear SW ID : 0x%x \n", DualRoleCf= g0)); + } + MmioWrite32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_ROLE_CFG0), Du= alRoleCfg0); + + DualRoleCfg1 =3D MmioRead32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUA= L_ROLE_CFG1)); + DEBUG ((DEBUG_INFO, "DualRoleCfg1 : 0x%x \n", DualRoleCfg1)); +} + +VOID +EFIAPI +UsbdMonitorEvents ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + USB_XDCI_DEV_CONTEXT *XdciDevContext; + UINT32 EventCount; + UINT32 PreEventCount; + UINT32 LoopCount; + + XdciDevContext =3D (USB_XDCI_DEV_CONTEXT *) Context; + EventCount =3D UsbRegRead ((UINT32)XdciDevContext->XdciMmioBarAddr, DWC_= XDCI_EVNTCOUNT_REG (0)); + if (EventCount =3D=3D 0) { + return; + } + + LoopCount =3D 0; + PreEventCount =3D EventCount; + while (EventCount !=3D 0) { + if (UsbDeviceIsrRoutineTimerBased (mDrvObj.XdciDrvObj) !=3D EFI_SUCCES= S) { + DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event ISR\n"= )); + } + EventCount =3D UsbRegRead ((UINT32)XdciDevContext->XdciMmioBarAddr, DW= C_XDCI_EVNTCOUNT_REG (0)); + if (PreEventCount =3D=3D EventCount) { + LoopCount++; + if (LoopCount >=3D 5) { + DEBUG ((DEBUG_INFO, "USB is working on a long event...\n")); + break; + } + } else { + LoopCount =3D 0; + } + } + + return; +} + +/** + Initializes the XDCI core + + @param MmioBar Address of MMIO BAR + @param XdciHndl Double pointer to for XDCI layer to set as an + opaque handle to the driver to be used in subsequen= t + interactions with the XDCI layer. + + @return EFI_SUCCESS if successfully initialized XDCI, EFI_DEVICE_ERROR o= therwise + +**/ +EFI_STATUS +UsbdInit ( + IN UINT32 MmioBar, + IN VOID **XdciHndl + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + USB_DEV_CONFIG_PARAMS ConfigParams; + + XhciSwitchSwid(TRUE); + + DEBUG ((DEBUG_INFO, "UsbdInit start\n")); + ConfigParams.ControllerId =3D USB_ID_DWC_XDCI; + ConfigParams.BaseAddress =3D MmioBar; + ConfigParams.Role =3D USB_ROLE_DEVICE; + ConfigParams.Speed =3D USB_SPEED_SUPER; + + Status =3D UsbDeviceInit (&ConfigParams, XdciHndl); + + DEBUG ((DEBUG_INFO, "UsbdInit status is %x\n", Status)); + DEBUG ((DEBUG_INFO, "ConfigParams.BaseAddress 0x%x\n", ConfigParams.Base= Address)); + + return Status; +} + + +/** + Copies relevant endpoint data from standard USB endpoint descriptors + to the usbEpInfo structure used by the XDCI + + @param EpDest destination structure + @param EpSrc source structure + + @return VOID + +**/ +VOID +UsbdSetEpInfo ( + IN USB_EP_INFO *EpDest, + IN USB_DEVICE_ENDPOINT_INFO *EpSrc + ) +{ + EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc =3D NULL; + EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR *EpCompDesc =3D NULL; + + // + // start by clearing all data in the destination + // + SetMem (EpDest, sizeof(USB_EP_INFO), 0); + EpDesc =3D EpSrc->EndpointDesc; + EpCompDesc =3D EpSrc->EndpointCompDesc; + + if (EpDesc !=3D NULL) { + EpDest->EpNum =3D EpDesc->EndpointAddress & 0x0F; //Bits 0-3 are ep nu= m + EpDest->EpDir =3D ((EpDesc->EndpointAddress & USB_ENDPOINT_DIR_IN) > 0= ) ? UsbEpDirIn : UsbEpDirOut; + EpDest->EpType =3D EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK; + EpDest->MaxPktSize =3D EpDesc->MaxPacketSize; + EpDest->Interval =3D EpDesc->Interval; + } + if (EpCompDesc !=3D NULL) { + EpDest->MaxStreams =3D EpCompDesc->Attributes & USB_EP_BULK_BM_ATTR_MA= SK; + EpDest->BurstSize =3D EpCompDesc->MaxBurst; + EpDest->Mult =3D EpCompDesc->BytesPerInterval; + } + + return; +} + + +/** + Initializes the given endpoint + + @param XdciHndl Pointer (handle) to the XDCI driver object + @param DevEpInfo Pointer to endpoint info structure + for the endpoint to initialize + + @return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise + +**/ +EFI_STATUS +UsbdInitEp ( + IN VOID *XdciHndl, + IN USB_DEVICE_ENDPOINT_INFO *DevEpInfo + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + USB_EP_INFO EpInfo; + + UsbdSetEpInfo (&EpInfo, DevEpInfo); + Status =3D UsbDeviceInitEp (XdciHndl, &EpInfo); + + return Status; +} + + +/** + Callback handler used when transfer operations complete. Calls + upper layer routine to handle the operation. + + @param XdciHndl Pointer (handle) to the XDCI driver object + @param XferReq Pointer to the transfer request structure + + @return VOID + +**/ +VOID +EFIAPI +UsbdXferDoneHndlr ( + IN VOID *XdciHndl, + IN USB_XFER_REQUEST *XferReq + ) +{ + EFI_USB_DEVICE_XFER_INFO XferInfo; + + DEBUG ((DEBUG_INFO, "UsbdXferDoneHndlr\n")); + + XferInfo.EndpointNum =3D (UINT8)XferReq->EpInfo.EpNum; + XferInfo.EndpointDir =3D XferReq->EpInfo.EpDir; + XferInfo.EndpointType =3D XferReq->EpInfo.EpType; + XferInfo.Buffer =3D XferReq->XferBuffer; + XferInfo.Length =3D XferReq->ActualXferLen; + + // + // If this is a non-control transfer complete, notify the class driver + // + if (XferInfo.EndpointNum > 0) { + if (mDrvObj.UsbdDevObj->DataCallback !=3D NULL) { + mDrvObj.UsbdDevObj->DataCallback (&XferInfo); + } + } + + return; +} + + +/** + Queue a request to transmit data + + @param XdciHndl Pointer (handle) to the XDCI driver object + @param IoReq Pointer to IO structure containing details of the + transfer request + + @return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise + +**/ +EFI_STATUS +UsbdEpTxData ( + IN VOID *XdciHndl, + IN USB_DEVICE_IO_REQ *IoReq + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + USB_XFER_REQUEST TxReq; + + // + //set endpoint data + // + UsbdSetEpInfo (&(TxReq.EpInfo), &(IoReq->EndpointInfo)); // set endpoint= data + + // + //if this is a control endpoint, set the number and direction + // + if (IoReq->EndpointInfo.EndpointDesc =3D=3D NULL) { + TxReq.EpInfo.EpNum =3D 0; + TxReq.EpInfo.EpDir =3D UsbEpDirIn; + } + + // + // setup the trasfer request + // + TxReq.XferBuffer =3D IoReq->IoInfo.Buffer; + TxReq.XferLen =3D IoReq->IoInfo.Length; + TxReq.XferDone =3D UsbdXferDoneHndlr; + + DEBUG ((DEBUG_INFO, "TX REQUEST: EpNum: 0x%x, epDir: 0x%x, epType: 0x%x= , MaxPktSize: 0x%x\n",\ + TxReq.EpInfo.EpNum, TxReq.EpInfo.EpDir, TxReq.EpInfo.EpType, TxR= eq.EpInfo.MaxPktSize)); + + Status =3D UsbXdciDeviceEpTxData (XdciHndl, &TxReq); + + return Status; +} + + +/** + Queue a request to receive data + + @param XdciHndl Pointer (handle) to the XDCI driver object + @param IoReq Pointer to IO structure containing details of the + receive request + + @return EFI_SUCCESS if operation succeeded, EFI_DEVICE_ERROR otherwise + +**/ +EFI_STATUS +UsbdEpRxData ( + IN VOID *XdciHndl, + IN USB_DEVICE_IO_REQ *IoReq + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + USB_XFER_REQUEST RxReq; + UINT32 ReqPacket; + + DEBUG ((DEBUG_INFO, "RX REQUEST in: IoReq->IoInfo.Length: 0x%x\n", IoRe= q->IoInfo.Length)); + DEBUG ((DEBUG_INFO, "RX REQUEST in: MaxPacketSize: 0x%x\n", IoReq->Endp= ointInfo.EndpointDesc->MaxPacketSize)); + + if (IoReq->EndpointInfo.EndpointDesc->MaxPacketSize =3D=3D 0) { + return EFI_DEVICE_ERROR; + } + + // + // set endpoint data + // + UsbdSetEpInfo (&(RxReq.EpInfo), &(IoReq->EndpointInfo)); + + // + // setup the trasfer request + // + RxReq.XferBuffer =3D IoReq->IoInfo.Buffer; + + // + // Transfer length should be multiple of USB packet size. + // + ReqPacket =3D IoReq->IoInfo.Length / IoReq->EndpointInfo.EndpointDesc->M= axPacketSize; + ReqPacket =3D ((IoReq->IoInfo.Length % IoReq->EndpointInfo.EndpointDesc-= >MaxPacketSize) =3D=3D 0)? ReqPacket : ReqPacket + 1; + RxReq.XferLen =3D ReqPacket * IoReq->EndpointInfo.EndpointDesc->MaxPacke= tSize; + + RxReq.XferDone =3D UsbdXferDoneHndlr; + + DEBUG ((DEBUG_INFO, "RX REQUEST: EpNum: 0x%x, epDir: 0x%x, epType: 0x%x= \n",\ + RxReq.EpInfo.EpNum, RxReq.EpInfo.EpDir, RxReq.EpInfo.EpType)); + DEBUG ((DEBUG_INFO, "RX REQUEST send: XferLen: 0x%x\n", RxReq.XferLen))= ; + + Status =3D UsbXdciDeviceEpRxData (XdciHndl, &RxReq); + + return Status; +} + + +/** + Callback used to handle Reset events from the XDCI + + @param Param Pointer to a generic callback parameter structure + + @return XDCI usb status + +**/ +EFI_STATUS +EFIAPI +UsbdResetEvtHndlr ( + IN USB_DEVICE_CALLBACK_PARAM *Param + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + DEBUG ((DEBUG_INFO, "UsbdResetEvtHndlr\n")); + + // + // reset device address to 0 + // + Status =3D UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "UsbdResetHdlr() - Failed to set address in XDCI\n= ")); + } + + return Status; +} + + +/** + Callback used to handle Connection done events from the XDCI + + @param Param Pointer to a generic callback parameter structure + + @return XDCI usb status + +**/ +EFI_STATUS +EFIAPI +UsbdConnDoneEvtHndlr ( + IN USB_DEVICE_CALLBACK_PARAM *Param + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + DEBUG ((DEBUG_INFO, "UsbdConnDoneEvtHndlr\n")); + + // + //reset device address to 0 + // + Status =3D UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDC= I\n")); + } + + // + // set the device state to attached/connected + // + mDrvObj.State =3D UsbDevStateAttached; + + return Status; +} + + +/** + Callback used to handle Control Endpoint Setup events from the XDCI + + @param Param Pointer to a generic callback parameter structure + + @return XDCI usb status + +**/ +EFI_STATUS +EFIAPI +UsbdSetupEvtHndlr ( + IN USB_DEVICE_CALLBACK_PARAM *Param + ) +{ + EFI_STATUS Status =3D EFI_SUCCESS; + EFI_USB_DEVICE_REQUEST Req; + + DEBUG ((DEBUG_INFO, "UsbdSetupEvtHndlr\n")); + + // + // Fill out request object from the incomming Buffer + // + CopyMem (&Req, Param->Buffer, sizeof(EFI_USB_DEVICE_REQUEST)); + + Status =3D UsbdSetupHdlr (&Req); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "UsbdSetupEvtHndlr: EFI_DEVICE_ERROR\n")); + } + + return Status; +} + + +/** + * Callback used to handle XferNotReady events from the XDCI + * + * @param Param Pointer to a generic callback parameter structure + * + * @return XDCI usb status + */ +EFI_STATUS +EFIAPI +UsbdNrdyEvtHndlr ( + IN USB_DEVICE_CALLBACK_PARAM *Param + ) +{ + DEBUG ((DEBUG_INFO, "UsbdNrdyEvtHndlr\n")); + return EFI_SUCCESS; +} + + +/** + Registers callbacks for event handlers with the XDCI layer. + The functions will be called as the registered events are triggered. + + @param XdciHndl to XDCI core driver + @return EFI_SUCCESS if successful, EFI_DEVICE_ERROR otherwise + +**/ +EFI_STATUS +UsbdRegisterCallbacks ( + IN VOID *XdciHndl + ) +{ + if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_RESET_EVENT, UsbdRes= etEvtHndlr) !=3D EFI_SUCCESS) { + goto UdciRegCallbackError; + } + + if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_CONNECTION_DONE, Usb= dConnDoneEvtHndlr) !=3D EFI_SUCCESS) { + goto UdciRegCallbackError; + } + + if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_SETUP_PKT_RECEIVED, = UsbdSetupEvtHndlr) !=3D EFI_SUCCESS) { + goto UdciRegCallbackError; + } + + if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_XFER_NRDY, UsbdNrdyE= vtHndlr) !=3D EFI_SUCCESS) { + goto UdciRegCallbackError; + } + + return EFI_SUCCESS; + +UdciRegCallbackError: + return EFI_DEVICE_ERROR; +} + + +/** + Returns the configuration descriptor for this device. The data + Buffer returned will also contain all downstream interface and + endpoint Buffers. + + @param Buffer Pointer to destination Buffer to copy descriptor data t= o + @param DescIndex the index of the descriptor to return + @param ReqLen the length in bytes of the request Buffer + @param DataLen Pointer whos value is to be filled with the byte count = of + data copied to the output Buffer + + @return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR o= therwise + +**/ +EFI_STATUS +UsbdGetConfigDesc ( + IN VOID *Buffer, + IN UINT8 DescIndex, + IN UINT32 ReqLen, + IN UINT32 *DataLen + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + UINT8 NumConfigs =3D 0; + UINT32 ConfigLen =3D 0; + USB_DEVICE_CONFIG_OBJ *ConfigObj =3D NULL; + VOID *Descriptor =3D 0; + UINT32 Length =3D 0; + + DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc()\n")); + + // + // For a CONFIGURATION request we send back all descriptors branching ou= t + // from this descriptor including the INTERFACE and ENDPOINT descriptors + // + // + // Verify the requested configuration exists - check valid index + // + NumConfigs =3D mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations; + + if (DescIndex < NumConfigs) { + // + // get the configuration object using the index Offset + // + ConfigObj =3D (mDrvObj.UsbdDevObj->ConfigObjs + DescIndex); + // + // get the complete configuration Buffer block including Interface and= Endpoint data + // + Descriptor =3D ConfigObj->ConfigAll; + // + // The config descriptor TotalLength has the full value for all desc B= uffers + // + ConfigLen =3D ConfigObj->ConfigDesc->TotalLength; + // + // copy the data to the output Buffer + // + Length =3D MIN (ReqLen, ConfigLen); + CopyMem (Buffer, Descriptor, Length); + *DataLen =3D Length; + Status =3D EFI_SUCCESS; + } else { + DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc() - Invalid Config index: %i\n"= , DescIndex)); + } + + if (Status =3D=3D EFI_SUCCESS) { + if (ConfigObj !=3D NULL) { + PrintConfigDescriptor (ConfigObj->ConfigDesc); + } + } + + return Status; +} + + +/** + Sets the active configuration to the selected configuration index if it = exists + + @param CfgValue the configuration value to set + + @return EFI_SUCCESS if the configuration was set, EFI_DEVICE_ERROR other= wise + +**/ +EFI_STATUS +UsbdSetConfig ( + UINT8 CfgValue + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + UINT8 numConfigs =3D 0; + USB_DEVICE_CONFIG_OBJ *pConfigObj =3D NULL; + USB_DEVICE_INTERFACE_OBJ *pIfObj =3D NULL; + USB_DEVICE_ENDPOINT_OBJ *pEpObj =3D NULL; + UINT8 cfgItr =3D 0; + UINT8 ifItr =3D 0; + UINT8 epItr =3D 0; + USB_DEVICE_ENDPOINT_INFO EpInfo; + USB_EP_INFO UsbEpInfo; + + DEBUG ((DEBUG_INFO, "UsbdSetConfig()\n")); + // + // Verify the requested configuration exists - check valid index + // + numConfigs =3D mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations; + + if (CfgValue !=3D 0) { + // + // Search for a matching configuration + // + for (cfgItr =3D 0; cfgItr < numConfigs; cfgItr++) { + pConfigObj =3D (mDrvObj.UsbdDevObj->ConfigObjs + cfgItr); + if (pConfigObj->ConfigDesc->ConfigurationValue =3D=3D CfgValue) { + + // + // Set the active configuration object + // + mDrvObj.ActiveConfigObj =3D pConfigObj; + // + // Find all interface objects for this configuration + // + for (ifItr =3D 0; ifItr < pConfigObj->ConfigDesc->NumInterfaces; i= fItr++) { + pIfObj =3D (pConfigObj->InterfaceObjs + ifItr); + // + // Configure the Endpoints in the XDCI + // + for (epItr =3D 0; epItr < pIfObj->InterfaceDesc->NumEndpoints; e= pItr++) { + pEpObj =3D (pIfObj->EndpointObjs + epItr); + + EpInfo.EndpointDesc =3D pEpObj->EndpointDesc; + EpInfo.EndpointCompDesc =3D pEpObj->EndpointCompDesc; + + if (UsbdInitEp (mDrvObj.XdciDrvObj, &EpInfo) =3D=3D EFI_SUCCES= S) { + UsbdSetEpInfo(&UsbEpInfo, &EpInfo); + if (UsbDeviceEpEnable (mDrvObj.XdciDrvObj, &UsbEpInfo) =3D= =3D EFI_SUCCESS) { + Status =3D EFI_SUCCESS; + } else { + DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to enable en= dpoint\n")); + } + } else { + DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to initialize = endpoint\n")); + } + } + } + // + // Let the class driver know it is configured + // + if (Status =3D=3D EFI_SUCCESS) { + if (mDrvObj.UsbdDevObj->ConfigCallback !=3D NULL) { + mDrvObj.UsbdDevObj->ConfigCallback (CfgValue); + } + } + + mDrvObj.State =3D UsbDevStateConfigured; // we are now configured + + break; // break from config search loop + } + } + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Invalid requested configuration = value: %i\n", CfgValue)); + } + + return Status; +} + + +/** + Returns the currently active configuration value + + @param Buffer Pointer to destination Buffer to copy configuration val= ue to + @param ReqLen the length in bytes of the request Buffer + @param DataLen Pointer whos value is to be filled with the byte count = of + data copied to the output Buffer + + @return EFI_SUCCESS if config value is successfully copied, EFI_DEVICE_E= RROR otherwise + +**/ +EFI_STATUS +UsbdGetConfig ( + VOID *Buffer, + UINT32 ReqLen, + UINT32 *DataLen + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + DEBUG ((DEBUG_INFO, "UsbdGetConfig()\n")); + + if (ReqLen >=3D 1) { // length of data expected must be 1 + if (mDrvObj.ActiveConfigObj !=3D NULL) { // assure we have a config ac= tive + *DataLen =3D 1; // one byte for ConfigurationValue + *(UINT8*)Buffer =3D mDrvObj.ActiveConfigObj->ConfigDesc->Configurati= onValue; + + Status =3D EFI_SUCCESS; + } else { + DEBUG ((DEBUG_INFO, "UsbdGetConfig() - No active configuration avail= able\n")); + } + } else { + DEBUG ((DEBUG_INFO, "UsbdGetConfig() - Invalid data length\n")); + } + + return Status; +} + + +/** + Returns the requested string descriptor if it exists + + @param Buffer Pointer to destination Buffer to copy descriptor data t= o + @param DescIndex the index of the descriptor to return + @param LangId the target language ID + @param ReqLen the length in bytes of the request Buffer + @param DataLen Pointer whos value is to be filled with the byte count = of + data copied to the output Buffer + + @return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR o= therwise + +**/ +EFI_STATUS +UsbdGetStringDesc ( + VOID *Buffer, + UINT8 DescIndex, + UINT16 LangId, + UINT32 ReqLen, + UINT32 *DataLen + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + UINT32 Length =3D 0; + USB_STRING_DESCRIPTOR *StringDesc; + UINT8 Index =3D 0; + UINT8 StrLangEntries =3D 0; + BOOLEAN StrLangFound =3D FALSE; + + DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Index: 0x%x, LangId: 0x%x, ReqLe= n: 0x%x\n", DescIndex, LangId, ReqLen)); + + // + // index zero of the string table contains the supported language codes + // + if (DescIndex =3D=3D 0) { + StringDesc =3D (mDrvObj.UsbdDevObj->StringTable); + Length =3D MIN (ReqLen, StringDesc->Length); + CopyMem (Buffer, StringDesc, Length); + *DataLen =3D Length; + Status =3D EFI_SUCCESS; + } else { + + // + // Verify the requested language ID is supported. String descriptor Ze= ro + // (First entry in the string table) is expected to contain the langua= ge list. + // The requested language ID is specified in the Index member of the r= equest. + // + StringDesc =3D mDrvObj.UsbdDevObj->StringTable; // get language string= descriptor + StrLangEntries =3D ((StringDesc->Length - 2) >> 1); + DEBUG ((DEBUG_INFO, "StrLangEntries=3D%x\n", StrLangEntries)); + + DEBUG ((DEBUG_INFO, "Looking LangID: \n")); + + for (Index =3D 0; Index < StrLangEntries; Index++) { + DEBUG ((DEBUG_INFO, "LangID [%x]=3D %x\n", Index, StringDesc->LangID= [Index])); + + if (StringDesc->LangID [Index] =3D=3D LangId) { + DEBUG ((DEBUG_INFO, "Found it\n")); + StrLangFound =3D TRUE; + } + } + + // + // If we found a matching language, attempt to get the string index re= quested + // + if (StrLangFound =3D=3D TRUE) { + DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: StrLangFound=3DFound, DescIn= dex=3D%x, StrTblEntries=3D%x\n", DescIndex, mDrvObj.UsbdDevObj->StrTblEntri= es)); + + if (DescIndex < mDrvObj.UsbdDevObj->StrTblEntries) { + // + // get the string descriptor for the requested index + // + StringDesc =3D (mDrvObj.UsbdDevObj->StringTable + DescIndex); + + Length =3D MIN (ReqLen, StringDesc->Length); + DEBUG ((DEBUG_INFO, "ReqLen=3D%x, StringLength=3D%x, Length=3D%x\n= ", ReqLen, StringDesc->Length, Length)); + + CopyMem (Buffer, StringDesc, Length); + *DataLen =3D Length; + Status =3D EFI_SUCCESS; + } else { + DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Invalid String index in US= B_REQ_GET_DESCRIPTOR request\n")); + } + } else { + DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Unsupported String Language = ID for USB_REQ_GET_DESCRIPTOR request\n")); + } + } + + if (Status =3D=3D EFI_SUCCESS) { + PrintStringDescriptor (StringDesc); + } + return Status; +} + + +#ifdef SUPPORT_SUPER_SPEED +/** + Returns the configuration descriptor for this device. The data + Buffer returned will also contain all downstream interface and + endpoint Buffers. + + @param Buffer Pointer to destination Buffer to copy descriptor data t= o + @param ReqLen the length in bytes of the request Buffer + @param DataLen Pointer whos value is to be filled with the byte count = of + data copied to the output Buffer + + @return EFI_SUCCESS if descritor successfully copied, EFI_DEVICE_ERROR o= therwise + +**/ +EFI_STATUS +UsbdGetBOSDesc ( + IN VOID *Buffer, + IN UINT32 ReqLen, + IN UINT32 *DataLen + ) +{ + EFI_USB_BOS_DESCRIPTOR *BosDesc =3D 0; + UINT32 Length =3D 0; + + DEBUG ((DEBUG_INFO, "UsbdGetBOSDesc()\n")); + + BosDesc =3D mDrvObj.UsbdDevObj->BosDesc; + Length =3D MIN (ReqLen, mDrvObj.UsbdDevObj->BosDesc->TotalLength); + + CopyMem(Buffer, BosDesc, Length); + *DataLen =3D Length; + + PrintBOSDescriptor (BosDesc); + + return EFI_SUCCESS; +} +#endif + +/** + Returns the current status for Device/Interface/Endpoint + + @param Buffer Pointer to destination Buffer to copy descriptor data t= o + @param ReqType The type of status to get + @param ReqLen the length in bytes of the request Buffer + @param DataLen Pointer whos value is to be filled with the byte count = of + data copied to the output Buffer + + @return EFI_SUCCESS if status successfully copied, EFI_DEVICE_ERROR othe= rwise + +**/ +EFI_STATUS +UsbdGetStatus ( + VOID *Buffer, + UINT8 ReqType, + UINT32 ReqLen, + UINT32 *DataLen + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + DEBUG ((DEBUG_INFO, "UsbdGetStatus()\n")); + + if (ReqLen >=3D 2) { // length of data must be at least 2 bytes + switch (ReqType & USB_TARGET_MASK) { + case USB_TARGET_DEVICE: + *DataLen =3D 2; // two byte for status + *(UINT16*)Buffer =3D USB_STATUS_SELFPOWERED; + Status =3D EFI_SUCCESS; + break; + + case USB_TARGET_INTERFACE: + // + // No implementation needed at this time + // + break; + + case USB_TARGET_ENDPOINT: + // + // No implementation needed at this time + // Should specify if endpoint is halted. Implement as necessary. + // + break; + + case USB_TARGET_OTHER: + // + // No implementation needed at this time + // + break; + + default: + break; + } + } else { + DEBUG ((DEBUG_INFO, "UsbdGetStatus() - Invalid data length\n")); + } + + return Status; +} + + +/** + Sets the address of the device + + @param address the address value to set + + @return EFI_SUCCESS if address was set, EFI_DEVICE_ERROR otherwise + +**/ +EFI_STATUS +UsbdSetAddress ( + UINT8 Address + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + DEBUG ((DEBUG_INFO, "UsbdSetAddress: setting address: 0x%x\n", Address))= ; + + if (Address <=3D 0x7F) { // address must not be > 127 + mDrvObj.Address =3D Address; + + // + // Configure Address in the XDCI + // + Status =3D UsbDeviceSetAddress (mDrvObj.XdciDrvObj, mDrvObj.Address); + if (!EFI_ERROR (Status)) { + mDrvObj.State =3D UsbDevStateAddress; + } else { + DEBUG ((DEBUG_INFO, "UsbdSetAddress: Failed to set address in XDCI\n= ")); + } + } else { + DEBUG ((DEBUG_INFO, "UsbdSetAddress: Invalid address: 0x%x\n", Address= )); + } + + return Status; +} + + +/** + Handles Setup device requests. Standard requests are immediately + handled here, and any Class/Vendor specific requests are forwarded + to the class driver + + @param CtrlRequest Pointer to a device request + + @return EFI_SUCCESS if request successfully handled, FALSE otherwise + +**/ +EFI_STATUS +UsbdSetupHdlr ( + IN EFI_USB_DEVICE_REQUEST *CtrlRequest + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + UINT8 DescIndex =3D 0; + USB_DEVICE_DESCRIPTOR *DevDesc =3D 0; + + // + // Initialize the IO object + // + mCtrlIoReq.IoInfo.Length =3D 0; + + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr start\n")); + PrintDeviceRequest (CtrlRequest); + + // + // Handle Standard Device Requests + // + if ((CtrlRequest->RequestType & USB_REQ_TYPE_MASK) =3D=3D USB_REQ_TYPE_S= TANDARD) { + switch (CtrlRequest->Request) { + case USB_REQ_GET_DESCRIPTOR: + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Host requests get descriptor\n= ")); + if (CtrlRequest->RequestType =3D=3D USB_RT_TX_DIR_D_TO_H) { + DescIndex =3D (CtrlRequest->Value & 0xff); // low byte is the in= dex requested + switch (CtrlRequest->Value >> 8) { // high byte contains request= type + case USB_DESC_TYPE_DEVICE: + DEBUG ((DEBUG_INFO, "Descriptor tyep: Device\n")); + DevDesc =3D mDrvObj.UsbdDevObj->DeviceDesc; + // + // copy the data to the output Buffer + // + mCtrlIoReq.IoInfo.Length =3D MIN (CtrlRequest->Length, DevDe= sc->Length); + CopyMem (mCtrlIoReq.IoInfo.Buffer, DevDesc, mCtrlIoReq.IoInf= o.Length); + PrintDeviceDescriptor (DevDesc); + break; + + case USB_DESC_TYPE_CONFIG: + DEBUG ((DEBUG_INFO, "Descriptor tyep: Configuration\n")); + Status =3D UsbdGetConfigDesc ( + mCtrlIoReq.IoInfo.Buffer, + DescIndex, + CtrlRequest->Length, + &(mCtrlIoReq.IoInfo.Length) + ); + break; + + case USB_DESC_TYPE_STRING: + DEBUG ((DEBUG_INFO, "Descriptor tyep: String\n")); + Status =3D UsbdGetStringDesc ( + mCtrlIoReq.IoInfo.Buffer, + DescIndex, + CtrlRequest->Index, + CtrlRequest->Length, + &(mCtrlIoReq.IoInfo.Length) + ); + break; + +#ifdef SUPPORT_SUPER_SPEED + case USB_DESC_TYPE_BOS: + DEBUG ((DEBUG_INFO, "Descriptor tyep: BOS\n")); + Status =3D UsbdGetBOSDesc ( + mCtrlIoReq.IoInfo.Buffer, + CtrlRequest->Length, + &(mCtrlIoReq.IoInfo.Length) + ); + break; + + case USB_DESC_TYPE_SS_ENDPOINT_COMPANION: + DEBUG ((DEBUG_INFO, "Descriptor tyep: Endpoint Companion\n")= ); + break; +#endif + + default: + DEBUG ((DEBUG_INFO, "Descriptor tyep: Unsupported, USB_REQ_G= ET_DESCRIPTOR request: 0x%x\n", (CtrlRequest->Value >> 8))); + break; + } + } else { + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr() - Invalid direction for USB= _REQ_GET_DESCRIPTOR request\n")); + } + break; + + case USB_REQ_GET_CONFIG: + DEBUG ((DEBUG_INFO, "USB_REQ_GET_CONFIG\n")); + if (CtrlRequest->RequestType =3D=3D USB_RT_TX_DIR_D_TO_H) { + Status =3D UsbdGetConfig (mCtrlIoReq.IoInfo.Buffer, CtrlRequest-= >Length, &(mCtrlIoReq.IoInfo.Length)); + } else { + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_RE= Q_GET_CONFIG request\n")); + } + break; + + case USB_REQ_SET_CONFIG: + DEBUG ((DEBUG_INFO, "USB_REQ_SET_CONFIG\n")); + if (CtrlRequest->RequestType =3D=3D USB_RT_TX_DIR_H_TO_D) { + Status =3D UsbdSetConfig ((UINT8)CtrlRequest->Value); + } else { + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_RE= Q_SET_CONFIG request\n")); + } + break; + + case USB_REQ_SET_ADDRESS: + DEBUG ((DEBUG_INFO, "USB_REQ_SET_ADDRESS\n")); + if (CtrlRequest->RequestType =3D=3D USB_RT_TX_DIR_H_TO_D) { + Status =3D UsbdSetAddress ((UINT8)CtrlRequest->Value); + } else { + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_RE= Q_SET_ADDRESS request\n")); + } + break; + + case USB_REQ_GET_STATUS: + DEBUG ((DEBUG_INFO, "USB_REQ_GET_STATUS\n")); + if (CtrlRequest->RequestType & USB_RT_TX_DIR_D_TO_H) { + Status =3D UsbdGetStatus (mCtrlIoReq.IoInfo.Buffer, CtrlRequest-= >RequestType, CtrlRequest->Length, &(mCtrlIoReq.IoInfo.Length)); + } else { + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_RE= Q_GET_STATUS request\n")); + } + break; +#ifdef SUPPORT_SUPER_SPEED + case USB_REQ_CLEAR_FEATURE: + case USB_REQ_SET_FEATURE: + case USB_REQ_SET_DESCRIPTOR: + case USB_REQ_GET_INTERFACE: + case USB_REQ_SET_INTERFACE: + case USB_REQ_SYNCH_FRAME: +#endif + default: + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Unsupported Standard Request:= 0x%x\n", CtrlRequest->Request)); + break; + } + } else { // This is not a Standard request, it specifies Class/Vendor ha= ndling + // + // Forward request to class driver + // + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Class/Vendor Request\n")); + if (mDrvObj.UsbdDevObj->SetupCallback !=3D NULL) { + mDrvObj.UsbdDevObj->SetupCallback (CtrlRequest, &(mCtrlIoReq.IoInfo)= ); + } + } + + DEBUG ((DEBUG_INFO, "dataLen=3D%x\n", mCtrlIoReq.IoInfo.Length)); + // + // Transfer data according to request if necessary + // + if (mCtrlIoReq.IoInfo.Length> 0) { + Status =3D UsbdEpTxData (mDrvObj.XdciDrvObj, &mCtrlIoReq); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Failed to TX data\n")); + } + } else { + // + // If we are not responding with data, send control status + // + Status =3D UsbDeviceEp0TxStatus (mDrvObj.XdciDrvObj); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Failed to Tx Ep0 Status\n")); + } + } + + return Status; +} + + +/** + Handles Connection done events. Sets the device address to zero. + + @return EFI_SUCCESS if able to set the address, EFI_DEVICE_ERROR otherwi= se + +**/ +EFI_STATUS +UsbdConnDoneHdlr ( + VOID + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr()\n")); + + // + // reset device address to 0 + // + Status =3D UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDC= I\n")); + } + + // + // set the device state to attached/connected + // + mDrvObj.State =3D UsbDevStateAttached; + + return Status; +} + + +/** + Handles transmit/receive completion events. Directly handles + control endpoint events and forwards class/vendor specific events + to the class drivers. + + @param XferInfo Pointer to Xfer structure + + @return + +**/ +VOID +UsbdXferDoneHdlr ( + IN EFI_USB_DEVICE_XFER_INFO *XferInfo + ) +{ + // + // If this is a non-control transfer complete, notify the class driver + // + if (XferInfo->EndpointNum > 0) { + if (mDrvObj.UsbdDevObj->DataCallback !=3D NULL) { + mDrvObj.UsbdDevObj->DataCallback (XferInfo); + } + } + + return; +} + + +/** + Binds a USB class driver with this USB device driver core. + After calling this routine, the driver is ready to begin + USB processing. + + @param UsbdDevObj Pointer to a usbd device object which contains + all relevant information for the class driver devic= e + + @return TRUE if binding was successful, FALSE otherwise + +**/ +EFI_STATUS +EFIAPI +UsbDeviceBind ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This, + IN USB_DEVICE_OBJ *UsbdDevObj + ) +{ + EFI_STATUS Status =3D EFI_SUCCESS; + + // + // allocate Tx Buffer + // + mCtrlIoReq.IoInfo.Buffer =3D AllocateZeroPool (USB_EPO_MAX_PKT_SIZE_ALL)= ; + if (mCtrlIoReq.IoInfo.Buffer !=3D NULL) { + mDrvObj.UsbdDevObj =3D UsbdDevObj; + mDrvObj.ActiveConfigObj =3D NULL; + mDrvObj.Address =3D 0; + mDrvObj.State =3D UsbDevStateInit; + } else { + DEBUG ((DEBUG_INFO, "UsbDeviceBind() - Failed to allocate IO Buffer\n"= )); + Status =3D EFI_DEVICE_ERROR; + } + + return Status; +} + + +/** + Unbinds the USB class driver from this USB device driver core. + + @return TRUE if successful, FALSE otherwise + +**/ +EFI_STATUS +EFIAPI +UsbDeviceUnbind ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ) +{ + mDrvObj.UsbdDevObj =3D NULL; + mDrvObj.ActiveConfigObj =3D NULL; + mDrvObj.Address =3D 0; + mDrvObj.State =3D UsbDevStateOff; + mDrvObj.XdciInitialized =3D FALSE; + + // + // release allocated Buffer data + // + if (mCtrlIoReq.IoInfo.Buffer) { + FreePool (mCtrlIoReq.IoInfo.Buffer); + } + + return EFI_SUCCESS; +} + + +/** + Performs continual USB device event processing until a cancel + event occurs + + @param TimeoutMs Connection timeout in ms. If 0, waits forever. + @return TRUE if run executed normally, FALSE if error ocurred + +**/ +EFI_STATUS +EFIAPI +UsbDeviceRun ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This, + IN UINT32 TimeoutMs + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + USB_XDCI_DEV_CONTEXT *XdciDevContext; + + XdciDevContext =3D USBUSBD_CONTEXT_FROM_PROTOCOL (This); + + // + // can only run if XDCI is initialized + // + if ((mDrvObj.XdciInitialized =3D=3D TRUE)) { + + if ((mDrvObj.State =3D=3D UsbDevStateConfigured) && (XdciDevContext->X= dciPollTimer =3D=3D NULL)) { + Status =3D gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + UsbdMonitorEvents, + XdciDevContext, + &XdciDevContext->XdciPollTimer + ); + if (!EFI_ERROR (Status)) { + Status =3D gBS->SetTimer (XdciDevContext->XdciPollTimer, TimerPeri= odic, EFI_TIMER_PERIOD_MILLISECONDS (20)); + DEBUG ((EFI_D_ERROR, "UsbDeviceRun Create Event\n")); + } + } + + mXdciRun =3D TRUE; // set the run flag to active + Status =3D EFI_SUCCESS; + + // + // start the Event processing loop + // + while (TRUE) { + if (XdciDevContext->XdciPollTimer =3D=3D NULL) { + if (UsbDeviceIsrRoutine (mDrvObj.XdciDrvObj) !=3D EFI_SUCCESS) { + DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event IS= R\n")); + } + } + + // + // Check if a run cancel request exists, if so exit processing loop + // + if (mXdciRun =3D=3D FALSE) { + if (XdciDevContext->XdciPollTimer !=3D NULL) { + DEBUG ((EFI_D_ERROR, "UsbDeviceRun close Event\n")); + gBS->SetTimer (XdciDevContext->XdciPollTimer, TimerCancel, 0); + gBS->CloseEvent (XdciDevContext->XdciPollTimer); + XdciDevContext->XdciPollTimer =3D NULL; + } + Status =3D EFI_SUCCESS; + DEBUG ((DEBUG_INFO, "UsbDeviceRun() - processing was cancelled\n")= ); + break; + } + + // + // check for timeout + // + if (TimeoutMs =3D=3D 0) + return EFI_TIMEOUT; + gBS->Stall (50); + TimeoutMs--; + } + } + + return Status; +} + + +/** + Sets a flag to stop the running device processing loop + + @return TRUE always + +**/ +EFI_STATUS +EFIAPI +UsbDeviceStop ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ) +{ + mXdciRun =3D FALSE; // set run flag to FALSE to stop processing + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +UsbDeviceInitXdci ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + USB_XDCI_DEV_CONTEXT *XdciDevContext; + + XdciDevContext =3D USBUSBD_CONTEXT_FROM_PROTOCOL (This); + + PlatformSpecificInit (); + + if (mDrvObj.XdciInitialized =3D=3D FALSE) { + if (XdciDevContext->XdciMmioBarAddr !=3D 0) { + + // + // Initialize device controller driver + // + DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Initializing Controller..= .\n")); + + // + // Initialize the device controller interface + // + if (UsbdInit ((UINT32)XdciDevContext->XdciMmioBarAddr, &mDrvObj.Xdci= DrvObj) =3D=3D EFI_SUCCESS) { + + // + // Setup callbacks + // + if (UsbdRegisterCallbacks (mDrvObj.XdciDrvObj) =3D=3D EFI_SUCCESS)= { + + mDrvObj.XdciInitialized =3D TRUE; + Status =3D EFI_SUCCESS; + + DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Controller initializa= tion complete\n")); + } else { + DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to register UD= CI callbacks\n")); + } + } else { + DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to initialize UD= CI\n")); + } + } else { + DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI MMIO BAR not set\n")= ); + } + } else { + DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI already initialized\n"= )); + Status =3D EFI_ALREADY_STARTED; + } + + return Status; +} + + +EFI_STATUS +EFIAPI +UsbDeviceConnect( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + DEBUG ((DEBUG_INFO, "UsbDeviceConnect \n")); + if (UsbXdciDeviceConnect (mDrvObj.XdciDrvObj) =3D=3D EFI_SUCCESS) { + Status =3D EFI_SUCCESS; + } + return Status; +} + + +EFI_STATUS +EFIAPI +UsbDeviceDisConnect ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + DEBUG ((DEBUG_INFO, "UsbDeviceDisConnect \n")); + if (UsbDeviceDisconnect (mDrvObj.XdciDrvObj) =3D=3D EFI_SUCCESS) { + mDrvObj.State =3D UsbDevStateInit; + Status =3D EFI_SUCCESS; + } + + XhciSwitchSwid(FALSE); + return Status; +} + + +EFI_STATUS +EFIAPI +UsbDeviceEpTxData( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This, + IN USB_DEVICE_IO_REQ *IoRequest + ) +{ + EFI_STATUS Status; + + Status =3D UsbdEpTxData (mDrvObj.XdciDrvObj, IoRequest); + return Status; +} + + +EFI_STATUS +EFIAPI +UsbDeviceEpRxData( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This, + IN USB_DEVICE_IO_REQ *IoRequest + ) +{ + EFI_STATUS Status; + + Status =3D UsbdEpRxData (mDrvObj.XdciDrvObj, IoRequest); + return Status; +} + + +// +// The Runtime UsbDeviceMode Protocol instance produced by this driver +// +EFI_USB_DEVICE_MODE_PROTOCOL mUsbDeviceModeProtocol =3D { + UsbDeviceInitXdci, + UsbDeviceConnect, + UsbDeviceDisConnect, + UsbDeviceEpTxData, + UsbDeviceEpRxData, + UsbDeviceBind, + UsbDeviceUnbind, + UsbDeviceRun, + UsbDeviceStop +}; + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDe= viceMode.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDe= viceMode.h new file mode 100644 index 0000000..5445974 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceMod= e.h @@ -0,0 +1,39 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef _USB_DEVICE_MODE_DXE_H_ +#define _USB_DEVICE_MODE_DXE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "XdciCommon.h" +#include "XdciDevice.h" + + +/// +/// Function declaration +/// +EFI_STATUS +UsbdSetupHdlr ( + IN EFI_USB_DEVICE_REQUEST *CtrlRequest + ); + +extern EFI_USB_DEVICE_MODE_PROTOCOL mUsbDeviceModeProtocol; + +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFu= ncIo.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFuncIo= .c new file mode 100644 index 0000000..9a156ba --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFuncIo.c @@ -0,0 +1,2219 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "UsbDeviceDxe.h" + +// +// 16 bytes in a guid x 2 characters per byte, 4 chars for dashes and a NU= L +// +#define CHARS_IN_GUID (sizeof(GUID) * 2 + 4 + 1) + +// +// Strings that get sent with the USB Connection +// +static CHAR16 mUsbFnDxeMfgString[] =3D L"Intel Corporation"; +static CHAR16 mUsbFnDxeProductString[] =3D L"Broxton"; +static CHAR16 mUsbFnDxeSerialNumber[] =3D L"INT123456"; + +// +// Duplicated from MiscSystemManufacturerData.c Some parts of it will +// replaced with device-specific unique values. +// +static GUID mSmBiosUniqueGuid =3D { + 0x5e24fe9c, 0xc8d0, 0x45bd, 0xa7, 0x9f, 0x54, 0xea, 0x5f, 0xbd, 0x= 3d, 0x97 + }; + +EFI_USBFN_IO_PROTOCOL mUsbFunIoProtocol =3D { + EFI_USBFN_IO_PROTOCOL_REVISION, + DetectPort, + ConfigureEnableEndpoints, + GetEndpointMaxPacketSize, + GetDeviceInfo, + GetVendorIdProductId, + AbortTransfer, + GetEndpointStallState, + SetEndpointStallState, + EventHandler, + Transfer, + GetMaxTransferSize, + AllocateTransferBuffer, + FreeTransferBuffer, + StartController, + StopController, + SetEndpointPolicy, + GetEndpointPolicy +}; + + +EFI_STATUS +PrintEventBuffer( + IN EFI_USBFN_IO_PROTOCOL *This + ) +{ + UINT32 EventCount; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + XDCI_CORE_HANDLE *XdciCorePtr; + USB_DEV_CORE *UsbDeviceCorePtr; + UINT32 Index; + UINT32 *DbBufPtr; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + + EventCount =3D UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC= _XDCI_EVNTCOUNT_REG(0)); + + DbBufPtr =3D (UINT32*)(UINTN)XdciCorePtr->CurrentEventBuffer; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: XdciCorePtr->AlignedEventBuffers= 0x%08x\n", (UINTN)XdciCorePtr->AlignedEventBuffers)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: DUMP BUF_S\n")); + for (Index =3D 0; Index < ((EventCount / 4) + 1); Index++) { + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "0x%08x\n", DbBufPtr[Index])); + } + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: DUMP BUF_E\n")); + + return EFI_SUCCESS; +} + +/** +Debug End +**/ + +/** + Returns information about what type of device was attached. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL in= stance. + @param[out] PortType Returns the USB port type. + + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready = to + process this request or the device is not + attached to the host. + + +**/ +EFI_STATUS +EFIAPI +DetectPort ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT EFI_USBFN_PORT_TYPE *PortType + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + EFI_STATUS Status; + UINT8 Value8; + + DEBUG ((USB_FUIO_DEBUG_INFO, "DetectPort - Entry\n")); + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + // + // USBSRCDETRSLT Bit[5:2] + // Result of USB HW Source Detection algorithm + // Power-Domain: VRTC + // Result of USB HW Source Detection algorithm : + // 0000 =3D Not determined + // 0001 =3D SDP Attached + // 0010 =3D DCP Attached + // 0011 =3D CDP Attached + // 0100 =3D ACA Attached + // 0101 =3D SE1 Attached + // 0110 =3D MHL Attached + // 0111 =3D Floating D+/D- Attached + // 1000 =3D Other Attached + // 1001 =3D DCP detected by ext. USB PHY + // 1010-1111 =3D Rsvd + // Reset: 0000B + // + + Value8 =3DPmicRead8 (0x5E, 0X29); + if ((Value8 & 0x03) !=3D 0x02) { + *PortType =3D EfiUsbUnknownPort; + Status =3D EFI_NOT_READY; + goto out; + } + + Value8 =3D Value8 >> 2 & 0x0f; + Status =3D EFI_SUCCESS; + switch (Value8) { + case 1: + *PortType =3D EfiUsbStandardDownstreamPort; + break; + case 2: + *PortType =3D EfiUsbDedicatedChargingPort; + break; + case 3: + *PortType =3D EfiUsbChargingDownstreamPort; + break; + + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + *PortType =3D EfiUsbUnknownPort; + break; + case 0: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + *PortType =3D EfiUsbUnknownPort; + Status =3D EFI_NOT_READY; + break; + } + +out: + DEBUG ((USB_FUIO_DEBUG_INFO, "DetectPort - Exit\n")); + return EFI_SUCCESS; +} + + +/** + The AllocateTransferBuffer function allocates a memory region of Size by= tes + and returns the address of the allocated memory that satisfies underlyin= g + controller requirements in the location referenced by Buffer. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] Size The number of bytes to allocate for the tr= ansfer + Buffer. + @param[in] Buffer A pointer to a pointer to the allocated Bu= ffer + if the call succeeds; undefined otherwise. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval The requested transfer Buffer could not be allocated. + +**/ +EFI_STATUS +EFIAPI +AllocateTransferBuffer ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINTN Size, + OUT VOID **Buffer + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + VOID *AllocateBufferPtr; + USB_MEM_NODE *NodePtr; + + DEBUG ((USB_FUIO_DEBUG_INFO, "AllocateTransferBuffer - Entry\n")); + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + if (Size =3D=3D 0) { + Status =3D EFI_INVALID_PARAMETER; + goto ErrorExit; + } + + AllocateBufferPtr =3D AllocateZeroPool (Size); + + if (AllocateBufferPtr =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + // + // Create new node + // + Status =3D InsertNewNodeToHead (This, &NodePtr); + if (EFI_ERROR (Status)) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + NodePtr->Size =3D Size; + NodePtr->AllocatePtr =3D AllocateBufferPtr; + + *Buffer =3D AllocateBufferPtr; + + DEBUG ((USB_FUIO_DEBUG_INFO, "AllocateTransferBuffer addr 0x%08x\n", All= ocateBufferPtr)); + DEBUG ((USB_FUIO_DEBUG_INFO, "AllocateTransferBuffer - Exit\n")); + return EFI_SUCCESS; + +ErrorExit: + + DEBUG ((USB_FUIO_DEBUG_ERROR, "AllocateTransferBuffer - ERRROR %r\n",Sta= tus)); + return Status; +} + + +/** + Deallocates the memory allocated for the transfer Buffer by + AllocateTransferBuffer function. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] Buffer Buffer Pointer to the transfer Buffer + to deallocate. + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + +**/ +EFI_STATUS +EFIAPI +FreeTransferBuffer ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + DEBUG ((USB_FUIO_DEBUG_LOAD, "FreeTransferBuffer - Entry\n")); + + Status =3D RemoveNode (This, Buffer); + if (EFI_ERROR(Status)) { + DEBUG ((USB_FUIO_DEBUG_LOAD, "FreeTransferBuffer - ERROR\n")); + return EFI_INVALID_PARAMETER; + } + + DEBUG ((USB_FUIO_DEBUG_LOAD, "FreeTransferBuffer - Exit\n")); + return EFI_SUCCESS; +} + +/** + Configure endpoints Based on supplied device and configuration descripto= rs. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] DeviceInfo A pointer to EFI_USBFN_DEVICE_INFO instanc= e. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready t= o + process this request. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to + lack of resources. + +**/ +EFI_STATUS +EFIAPI +ConfigureEnableEndpoints ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USB_DEVICE_INFO *DeviceInfo + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + Status =3D EFI_SUCCESS; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "ConfigureEnableEndpoints - Entry\n")); + // + //Assuming that the hardware has already been initialized, + //this function configures the endpoints using supplied + //DeviceInfo, activates the port, and starts receiving USB events + // + Status =3D EFI_SUCCESS; + if (DeviceInfo =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + goto FUNC_EXIT; + } + + UsbFuncIoDevPtr->DevInfoPtr->DeviceDescriptor =3D DeviceInfo->DeviceDesc= riptor; + + // + // Set Configure table + // + if (DeviceInfo->DeviceDescriptor->NumConfigurations > 1) { + DEBUG ((EFI_D_ERROR, "!!!Error ConfigNum over '1' %d\n", DeviceInfo->D= eviceDescriptor->NumConfigurations)); + } + UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor =3D DeviceInfo->ConfigI= nfoTable[0]->ConfigDescriptor; + UsbFuncIoDevPtr->IndexPtrConfig.InterfaceInfoTable[0] =3D DeviceInfo->Co= nfigInfoTable[0]->InterfaceInfoTable[0]; + + // + // Set Interface + // + if (DeviceInfo->ConfigInfoTable[0]->ConfigDescriptor->NumInterfaces > 1)= { + DEBUG ((EFI_D_ERROR, "!!!Error NumInterfaces[0] over '1' %d\n", Device= Info->ConfigInfoTable[0]->ConfigDescriptor->NumInterfaces)); + } + UsbFuncIoDevPtr->IndexPtrInteface.InterfaceDescriptor =3D DeviceInfo->Co= nfigInfoTable[0]->InterfaceInfoTable[0]->InterfaceDescriptor; + + // + // Set Endpoint + // + if (UsbFuncIoDevPtr->IndexPtrInteface.InterfaceDescriptor->NumEndpoints = > 2) { + DEBUG ((EFI_D_ERROR, "!!!Error NumEndPoint[0] over '2' %d\n", UsbFuncI= oDevPtr->IndexPtrInteface.InterfaceDescriptor->NumEndpoints)); + } + + UsbFuncIoDevPtr->IndexPtrInEp.EndpointCompDesc =3D NULL; + UsbFuncIoDevPtr->IndexPtrOutEp.EndpointCompDesc =3D NULL; + + if ((DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDesc= riptorTable[0]->EndpointAddress & USB_ENDPOINT_DIR_IN) !=3D 0) { + UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc =3D DeviceInfo->ConfigInfoT= able[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[0]; + UsbFuncIoDevPtr->IndexPtrOutEp.EndpointDesc =3D DeviceInfo->ConfigInfo= Table[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[1]; + } else { + UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc =3D DeviceInfo->ConfigInfoT= able[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[1]; + UsbFuncIoDevPtr->IndexPtrOutEp.EndpointDesc =3D DeviceInfo->ConfigInfo= Table[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[0]; + } + + DEBUG ((USB_FUIO_DEBUG_LOAD, " In Ep Num 0x%02x\n", UsbFuncIoDevPtr->Ind= exPtrInEp.EndpointDesc->EndpointAddress)); + + DEBUG ((USB_FUIO_DEBUG_LOAD, " Out Ep Num 0x%02x\n", UsbFuncIoDevPtr->In= dexPtrOutEp.EndpointDesc->EndpointAddress)); + +FUNC_EXIT: + DEBUG ((USB_FUIO_DEBUG_LOAD, "ConfigureEnableEndpoints - exit %r\n", Sta= tus)); + return Status; +} + +/** + Returns the maximum packet size of the specified endpoint type for + the supplied bus Speed. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] EndpointType Endpoint type as defined as EFI_USB_ENDPOI= NT_TYPE. + @param[in] BusSpeed Bus Speed as defined as EFI_USB_BUS_SPEED. + @param[in] MaxPacketSize The maximum packet size, in bytes, + of the specified endpoint type. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready t= o + process this request. +**/ +EFI_STATUS +EFIAPI +GetEndpointMaxPacketSize ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USB_ENDPOINT_TYPE EndpointType, + IN EFI_USB_BUS_SPEED BusSpeed, + OUT UINT16 *MaxPacketSize + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + USB_DEV_CORE *DevCorePtr; + XDCI_CORE_HANDLE *XdciCorePtr; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + DevCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D DevCorePtr->ControllerHandle; + Status =3D EFI_SUCCESS; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointMaxPacketSize - Entry\n")); + + switch (EndpointType) { + case UsbEndpointControl: +#ifdef SUPPORT_SUPER_SPEED + *MaxPacketSize =3D USB_EP0_MAX_PKT_SIZE_SS; // Default to super Spee= d +#else + *MaxPacketSize =3D USB_EP0_MAX_PKT_SIZE_HS; // Default to high Speed +#endif + break; + + case UsbEndpointBulk: +#ifdef SUPPORT_SUPER_SPEED + *MaxPacketSize =3D USB_BULK_EP_PKT_SIZE_SS; // Default to super Spee= d +#else + *MaxPacketSize =3D USB_BULK_EP_PKT_SIZE_HS; // Default to high Speed +#endif + break; + + case UsbEndpointInterrupt: + *MaxPacketSize =3D 1; + break; + + case UsbEndpointIsochronous: + default: + Status =3D EFI_DEVICE_ERROR; + break; + } + + DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointMaxPacketSize - Exit %r\n", Sta= tus)); + return Status; +} + + +/** + Returns the maximum supported transfer size. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] MaxTransferSize The maximum supported transfer size, in by= tes. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready t= o + process this request. +**/ +EFI_STATUS +EFIAPI +GetMaxTransferSize ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT UINTN *MaxTransferSize + ) +{ + // + // Need to check, Make max transfer package to 8MB + // + *MaxTransferSize =3D MAX_TRANSFER_PACKET; + return EFI_SUCCESS; +} + + +/** + This function returns the unique device ID of the device--this matches + what is populated in the SMBIOS table. + + @param[in/out] BufferSize On input, the size of the Buffer in bytes. + On output, the amount of data returned in = Buffer + in bytes. + + @param[out] Buffer A pointer to a Buffer to return the reques= ted + information as a Unicode string. What stri= ng are + we talking about + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_BUFFER_TOO_SMALL A parameter is invalid. + +**/ +STATIC +EFI_STATUS +EFIAPI +GetDeviceSerialNumber ( + IN OUT UINTN *BufferSize, + OUT VOID *Buffer OPTIONAL + ) +{ + EFI_STATUS Status =3D EFI_SUCCESS; + CHAR16 UuidString[CHARS_IN_GUID]; + UINTN CharsCopied; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "+GetDeviceSerialNumber\n")); + // + // check bounds + // + if (*BufferSize < sizeof(UuidString)) { + Status =3D EFI_BUFFER_TOO_SMALL; + *BufferSize =3D 0; + goto Error; + } + + // + // The rest of mSmBiosUniqueGuid will be same. Note that we cannot + // read the SMBIOS table directly, as it might not be ready by the tim= e we + // are to read it. The population of the data from the eMMC is ready + // by the time we are here. + // + + // + // Print to to a string, and copy it off + // + CharsCopied =3D UnicodeSPrint(UuidString, sizeof(UuidString), L"%g", &= mSmBiosUniqueGuid); + if (CharsCopied !=3D (CHARS_IN_GUID - 1)) + { + Status =3D EFI_BUFFER_TOO_SMALL; + *BufferSize =3D 0; + goto Error; + } + CopyMem(Buffer, UuidString, sizeof(UuidString)); + *BufferSize =3D sizeof(UuidString); + +Error: + + DEBUG ((USB_FUIO_DEBUG_LOAD, "-GetDeviceSerialNumber, Status =3D 0x%08= x\r\n", Status)); + + return Status; +} + + +/** + Returns device specific information Based on the supplied identifier as + a Unicode string + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] Id Requested information id. + @param[in] BufferSize On input, the size of the Buffer in bytes. + On output, the amount of data returned in = Buffer + in bytes. + @param[in] Buffer A pointer to a Buffer to return the reques= ted + information as a Unicode string. What stri= ng are + we talking about + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready t= o + process this request. +**/ +EFI_STATUS +EFIAPI +GetDeviceInfo ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USBFN_DEVICE_INFO_ID Id, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer OPTIONAL + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + Status =3D EFI_SUCCESS; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "GetDeviceInfo - Entry\n")); + + if ((BufferSize =3D=3D 0) || (Buffer =3D=3D NULL)) { + Status =3D EFI_INVALID_PARAMETER; + goto FUN_EXIT; + } + + switch (Id) { + + // + // FIXME: Get real serial number of board + // + case EfiUsbDeviceInfoSerialNumber: + if (*BufferSize < sizeof(mUsbFnDxeSerialNumber)) { + Status =3D EFI_BUFFER_TOO_SMALL; + *BufferSize =3D 0; + goto FUN_EXIT; + } + CopyMem(Buffer, mUsbFnDxeSerialNumber, sizeof(mUsbFnDxeSerialNumbe= r)); + *BufferSize =3D sizeof(mUsbFnDxeSerialNumber); + break; + + case EfiUsbDeviceInfoManufacturerName: + if (*BufferSize < sizeof(mUsbFnDxeMfgString)) { + Status =3D EFI_BUFFER_TOO_SMALL; + *BufferSize =3D 0; + goto FUN_EXIT; + } + CopyMem(Buffer, mUsbFnDxeMfgString, sizeof(mUsbFnDxeMfgString)); + *BufferSize =3D sizeof(mUsbFnDxeMfgString); + break; + + case EfiUsbDeviceInfoProductName: + if (*BufferSize < sizeof(mUsbFnDxeProductString)) { + Status =3D EFI_BUFFER_TOO_SMALL; + *BufferSize =3D 0; + goto FUN_EXIT; + } + CopyMem(Buffer, mUsbFnDxeProductString, sizeof(mUsbFnDxeProductStr= ing)); + *BufferSize =3D sizeof(mUsbFnDxeProductString); + break; + + case EfiUsbDeviceInfoUnknown: + default: + Status =3D EFI_UNSUPPORTED; + *BufferSize =3D 0; + DEBUG ((USB_FUIO_DEBUG_ERROR, "Unknown ID %d encountered.\r\n", Id))= ; + break; + } + +FUN_EXIT: + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - ConfigDescriptor addr 0x= %08x \n", (UINTN)UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor)); + DEBUG ((USB_FUIO_DEBUG_LOAD, "GetDeviceInfo - Exit %r\n", Status)); + return Status; +} + + +/** + Returns vendor-id and product-id of the device. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[out] Vid Returned vendor-id of the device. + @param[out] Pid Returned product-id of the device. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Unable to return vid or pid. + +**/ +EFI_STATUS +EFIAPI +GetVendorIdProductId ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT UINT16 *Vid, + OUT UINT16 *Pid + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + // + // *Vid =3D 0x8086 + // *Pid =3D 0x0A65 + // + *Vid =3D UsbFuncIoDevPtr->VendorId; + *Pid =3D UsbFuncIoDevPtr->DeviceId; + return EFI_SUCCESS; +} + +/** + Aborts transfer on the specified endpoint. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] EndpointIndex Indicates the endpoint on which the ongoin= g + transfer needs to be canceled. + @param[in] Direction Direction of the endpoint. + + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready t= o + process this request. + +**/ +EFI_STATUS +EFIAPI +AbortTransfer ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + XDCI_CORE_HANDLE *XdciCorePtr; + USB_DEV_CORE *UsbDeviceCorePtr; + USB_EP_INFO EpInfo; + EFI_STATUS Status; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "FU:AbortTransfer - Entry\n")); + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + Status =3D EFI_SUCCESS; + + if (UsbFuncIoDevPtr->DevResetFlag =3D=3D TRUE) { + return Status; + } + + EpInfo.EpNum =3D EndpointIndex; + EpInfo.EpDir =3D Direction? UsbEpDirIn : UsbEpDirOut; + + Status =3D UsbDeviceEpCancelTransfer (UsbFuncIoDevPtr->DrvCore, &EpInfo)= ; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "FU:AbortTransfer - Exit %r\n", Status)); + return Status; +} + +/** + Returns the stall state on the specified endpoint. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] EndpointIndex Indicates the endpoint on which the ongoin= g + transfer needs to be canceled. + @param[in] Direction Direction of the endpoint. + @param[in] State Boolean, true value indicates that the end= point + is in a stalled state, false otherwise. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready t= o + process this request. + +**/ +EFI_STATUS +EFIAPI +GetEndpointStallState ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT BOOLEAN *State + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + XDCI_CORE_HANDLE *XdciCorePtr; + UINT32 EndPoint; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointStallState - Entry\n")); + + EndPoint =3D UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn = : UsbEpDirOut); + + XdciCorePtr =3D UsbFuncIoDevPtr->XdciDrvIfHandle; + + if (XdciCorePtr->EpHandles[EndPoint].State =3D=3D USB_EP_STATE_STALLED) = { + *State =3D TRUE; + } else { + *State =3D FALSE; + } + + DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointStallState - Exit\n")); + return EFI_SUCCESS; +} + + +EFI_STATUS +UsbSetAddress ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT32 Address + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + XDCI_CORE_HANDLE *XdciCorePtr; + USB_DEV_CORE *UsbDeviceCorePtr; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetAddress - 0x%04x Entry\n", Address))= ; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + Status =3D EFI_SUCCESS; + + Status =3D UsbDeviceSetAddress (UsbDeviceCorePtr, (UINT32)Address); + + if (Status !=3D EFI_SUCCESS) { + Status =3D EFI_DEVICE_ERROR; + goto EXIT_SET_ADDRESS; + } + + Status =3D UsbDeviceEp0TxStatus (UsbDeviceCorePtr); + + if (Status !=3D EFI_SUCCESS) { + Status =3D EFI_NO_RESPONSE; + goto EXIT_SET_ADDRESS; + } + +EXIT_SET_ADDRESS: + + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetAddress - Exit %r\n", Status)); + return Status; +} + + +EFI_STATUS +EFIAPI +UsbSetconfigure ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT32 InterFaceIndex + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + XDCI_CORE_HANDLE *XdciCorePtr; + USB_DEV_CORE *UsbDeviceCorePtr; + UINT32 InterfaceNum; + UINT32 EndPointNum; + UINT32 EndPointIndex; + EFI_USB_INTERFACE_INFO *InterfaceInfoPtr; + USB_EP_INFO EpInfo; + USB_DEVICE_ENDPOINT_INFO EpDescInfo; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - 0x%04x Entry\n", InterFa= ceIndex)); + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + Status =3D EFI_SUCCESS; + + InterfaceNum =3D UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor->NumIn= terfaces; + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - ConfigDescriptor addr 0x= %08x \n", (UINTN)UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor)); + + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - DescriptorType 0x%04x ; = ConfigurationValue 0x%04x\n", + UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor->DescriptorType= , + UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor->ConfigurationV= alue + )); + + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - InterfaceNum 0x%04x \n",= InterfaceNum)); + if (InterfaceNum < InterFaceIndex) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT__SET_CONFIGURE; + } + + // + // Arry strart form '0', Index start from '1'. + // + InterfaceInfoPtr =3D UsbFuncIoDevPtr->IndexPtrConfig.InterfaceInfoTable[= InterFaceIndex - 1]; + EndPointNum =3D InterfaceInfoPtr->InterfaceDescriptor->NumEndpoints; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - Total EP NUM 0x%04x \n",= EndPointNum)); + + for (EndPointIndex =3D 0; EndPointIndex < EndPointNum; EndPointIndex++) = { + EpDescInfo.EndpointDesc =3D InterfaceInfoPtr->EndpointDescriptorTable[= EndPointIndex]; + EpDescInfo.EndpointCompDesc =3D NULL; + UsbFnSetEpInfo (&EpInfo, &EpDescInfo); + DEBUG ((USB_FUIO_DEBUG_LOAD, "EndpointAddress 0x%02x\n", EpDescInfo.En= dpointDesc->EndpointAddress)); + + if (UsbDeviceInitEp (UsbDeviceCorePtr, &EpInfo) =3D=3D EFI_SUCCESS) { + if (UsbDeviceEpEnable (UsbDeviceCorePtr, &EpInfo) =3D=3D EFI_SUCCES= S) { + } else { + Status =3D EFI_DEVICE_ERROR; + DEBUG ((DEBUG_INFO, "UsbDeviceEpEnable() - Failed to enable endpo= int\n")); + } + } else { + Status =3D EFI_DEVICE_ERROR; + DEBUG ((DEBUG_INFO, "UsbDeviceInitEp() - Failed to initialize endpo= int\n")); + } + } + + Status =3D UsbDeviceEp0TxStatus (UsbDeviceCorePtr); + + if (Status !=3D EFI_SUCCESS) { + Status =3D EFI_NO_RESPONSE; + goto EXIT__SET_CONFIGURE; + } + + +EXIT__SET_CONFIGURE: + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - Exit %r\n", Status)); + + return Status; +} + +/** + Sets or clears the stall state on the specified endpoint. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] EndpointIndex Indicates the endpoint on which the ongoin= g + transfer needs to be canceled. + @param[in] Direction Direction of the endpoint. + @param[in] State Requested stall state on the specified end= point. + True value causes the endpoint to stall; + false value clears an existing stall. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready t= o + process this request. + +**/ +EFI_STATUS +EFIAPI +SetEndpointStallState ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN BOOLEAN State + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + USB_EP_INFO pEpInfo; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + DEBUG ((USB_FUIO_DEBUG_LOAD, "SetEndpointStallState - Entry\n")); + Status =3D EFI_SUCCESS; + + pEpInfo.EpNum =3D EndpointIndex; + pEpInfo.EpDir =3D Direction? UsbEpDirIn : UsbEpDirOut; + + if (State =3D=3D TRUE) { + Status =3D UsbDeviceEpStall (UsbFuncIoDevPtr->DrvCore, (VOID*)(UINTN) = &pEpInfo); + } else { + Status =3D UsbDeviceEpClearStall (UsbFuncIoDevPtr->DrvCore, (VOID*)(UI= NTN) &pEpInfo); + } + + if (Status !=3D EFI_SUCCESS) { + Status =3D EFI_DEVICE_ERROR; + } + + DEBUG ((USB_FUIO_DEBUG_LOAD, "SetEndpointStallState - Exit\n")); + return Status; +} + +EFI_STATUS +DeviceEventCheck( + IN EFI_USBFN_IO_PROTOCOL *This, + IN USBD_EVENT_BUF *EventIndex, + OUT UINT32 *ProcessSize, + OUT EFI_USBFN_MESSAGE *Message, + OUT BOOLEAN *EventFlag + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + UINT32 EventReg; + USB_DEV_CORE *UsbDeviceCorePtr; + XDCI_CORE_HANDLE *XdciCorePtr; + + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "\n FUEV::DeviceEvent entry....\n")); + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + EventReg =3D (EventIndex->Event & DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK); + EventReg >>=3D DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS; + *EventFlag =3D FALSE; + + // + // Assume default event size. Change it in switch case if + // different + // + *ProcessSize =3D DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES; + + switch (EventReg) { + case DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_DISCONN_EVENT\n")); + *Message =3D EfiUsbMsgBusEventDetach; + break; + + case DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_USB_RESET_EVENT\n")); + // + // In resetDet will prepare setup Xfer package + // + UsbFuncIoDevPtr->DevReConnect =3D FALSE; + UsbFuncIoDevPtr->DevResetFlag =3D TRUE; + + usbProcessDeviceResetDet (XdciCorePtr); + UsbDeviceSetAddress (UsbDeviceCorePtr, 0); + *Message =3D EfiUsbMsgBusEventReset; + *EventFlag =3D TRUE; + break; + + case DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_CONN_DONE_EVENT\n")); + usbProcessDeviceResetDone(XdciCorePtr); + UsbDeviceSetAddress(UsbDeviceCorePtr, 0); + UsbFuncIoDevPtr->DevReConnect =3D TRUE; + UsbFuncIoDevPtr->DevResetFlag =3D FALSE; + *EventFlag =3D TRUE; + *Message =3D EfiUsbMsgNone; + break; + + case DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_HBRNTN_REQ_EVENT\n")); + *Message =3D EfiUsbMsgBusEventSuspend; + *EventFlag =3D TRUE; + break; + + case DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_WKUP_EVENT\n")); + *Message =3D EfiUsbMsgBusEventResume; + break; + + case DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT: + *ProcessSize =3D DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES; + *Message =3D EfiUsbMsgNone; + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFUDwcXdciProcessDeviceEvent: UNH= ANDLED device event: %x\n", EventReg)); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_STATE_CHANGE_EVENT\n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_SOF_EVENT\n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_ERRATIC_ERR_EVENT\n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_CMD_CMPLT_EVENT\n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DE= V_BUFF_OVFL_EVENT\n")); + break; + + default: + *EventFlag =3D FALSE; + *Message =3D EfiUsbMsgNone; + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFUWcXdciProcessDeviceEvent: UNHA= NDLED device event: %x\n", EventReg)); + break; + } + + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "\n FUEV::DeviceEvent entry exit.... \n"= )); + return EFI_SUCCESS; +} + + +EFI_STATUS +Ep0XferDone( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT32 EndPointNum, + OUT EFI_USBFN_MESSAGE *Message, + IN OUT UINTN *PayloadSize, + OUT EFI_USBFN_MESSAGE_PAYLOAD *Payload + ) +{ + USB_DEV_CORE *UsbDeviceCorePtr; + XDCI_CORE_HANDLE *XdciCorePtr; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + DWC_XDCI_ENDPOINT *EpHandle; + DWC_XDCI_TRB *Trb; + UINT32 TrbCtrl; + UINT32 TrbSts; + UINT32 BufferLen; + EFI_STATUS DevStatus; + USB_EP_INFO EpInfo; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + EpHandle =3D &XdciCorePtr->EpHandles[EndPointNum]; + Trb =3D XdciCorePtr->Trbs + (EndPointNum * DWC_XDCI_TRB_NUM); + + if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) { + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0XferDone. HW owns TRB: %x!!!\n", (= UINT32)(UINTN)Trb)); + } + + DevStatus =3D EFI_SUCCESS; + BufferLen =3D 0; + + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "EndPointNum:%d, TRB: Addr 0x%08x!!!\n",= EndPointNum, (UINTN)Trb)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done Trb->TrbCtrl: %x!!!\n", (UINT3= 2)Trb->TrbCtrl)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done Trb->LenXferParams: %x!!!\n", = (UINT32)Trb->LenXferParams)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done Trb->BuffPtrLow: %x!!!\n", (UI= NT32)Trb->BuffPtrLow)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done Trb->BuffPtrHigh: %x!!!\n", (U= INT32)Trb->BuffPtrHigh)); + + // + // Set CheckFlag to FALSE for 'DwcXdciEpRxData' function + // check the RX request complete and continue next transfer request + // + EpHandle->CheckFlag =3D FALSE; + EpHandle->CurrentXferRscIdx =3D 0; + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D01!!\n")); + TrbCtrl =3D (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_TYPE_MASK) >> DWC_XDCI_TRB= _CTRL_TYPE_BIT_POS; + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D02!!\n")); + TrbSts =3D (Trb->LenXferParams & DWC_XDCI_TRB_STATUS_MASK) >> DWC_XDCI_T= RB_STATUS_BIT_POS; + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D03!!\n" )); + BufferLen =3D Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK; + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D04 TrbCtrl :: %x!!\n", TrbCtr= l)); + switch (TrbCtrl) { + case DWC_XDCI_TRB_CTRL_TYPE_SETUP: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done DWC_XDCI_TRB_CTRL_TYPE_SET= UP!!\n")); + // + // This is delay for other host USB controller(none Intel), identify= device get fail issue. + // + gBS->Stall(130); + BufferLen =3D 8; + + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "DWC_XDCI_TRB_CTRL_TYPE_SETUP!!\n"))= ; + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "AlignedSetupBuffer::0x%08x!!\n", Xd= ciCorePtr->AlignedSetupBuffer)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Payload::0x%08x!!\n", (UINTN)Payloa= d)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "BufferLen::0x%08x!!\n", (UINTN)Buff= erLen)); + *Message =3D EfiUsbMsgSetupPacket; + CopyMem (Payload, XdciCorePtr->AlignedSetupBuffer, BufferLen); + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D06!!\n")); + if (!(XdciCorePtr->AlignedSetupBuffer[0] & USB_SETUP_DATA_PHASE_DIRE= CTION_MASK)) { + if ((XdciCorePtr->AlignedSetupBuffer[0] =3D=3D 0x00) ) { + if ((XdciCorePtr->AlignedSetupBuffer[1] =3D=3D USB_DEV_SET_ADDR= ESS)) { + // + // set address + // + UsbSetAddress ( + This, + (UINT32)(XdciCorePtr->AlignedSetupBuffer[3] << 8 | XdciCoreP= tr->AlignedSetupBuffer[2]) + ); + + *Message =3D EfiUsbMsgNone; + } else if ((XdciCorePtr->AlignedSetupBuffer[1] =3D=3D USB_DEV_S= ET_CONFIGURATION)) { + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "\n set configure !!!")); + UsbSetconfigure ( + This, + (UINT32)(XdciCorePtr->AlignedSetupBuffer[3] << 8 | XdciCoreP= tr->AlignedSetupBuffer[2]) + ); + *Message =3D EfiUsbMsgNone; + } + } + } + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D07!!\n")); + break; + + case DWC_XDCI_TRB_CTRL_TYPE_DATA: + DEBUG ((DEBUG_INFO, "Ep0 done DWC_XDCI_TRB_CTRL_TYPE_DATA!!\n")); + // + // Notify upper layer of control transfer completion + // if a callback function was registerd + // + if ((EndPointNum & 0x01) =3D=3D 0) { + *Message =3D EfiUsbMsgEndpointStatusChangedRx; + } else { + *Message =3D EfiUsbMsgEndpointStatusChangedTx; + } + Payload->utr.EndpointIndex =3D (UINT8)(EndPointNum >> 1); + Payload->utr.Direction =3D (UINT8)(EndPointNum & 0x01); + Payload->utr.Buffer =3D (VOID*)(UINTN)(Trb->BuffPtrLow); + + DEBUG ((DEBUG_INFO, "Ep0 EndPointNum: %x!!!\n", (UINT32)EndPointNum)= ); + DEBUG ((DEBUG_INFO, "Ep0 done XferLength: %x!!!\n", (UINT32)UsbFuncI= oDevPtr->EndPointXferRec[EndPointNum].XferLength)); + Payload->utr.Buffer =3D (VOID*)UsbFuncIoDevPtr->EndPointXferRec[EndP= ointNum].XferAddress; + Payload->utr.BytesTransferred =3D UsbFuncIoDevPtr->EndPointXferRec[E= ndPointNum].XferLength; + + if (TrbSts =3D=3D 0) { + if ((Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK) =3D=3D 0) { + Payload->utr.TransferStatus =3D UsbTransferStatusComplete; + } else { + Payload->utr.TransferStatus =3D UsbTransferStatusActive; + } + } else if (TrbSts !=3D 0) { + Trb->TrbCtrl |=3D DWC_XDCI_TRB_CTRL_HWO_MASK; + *Message =3D EfiUsbMsgNone; + Payload->utr.TransferStatus =3D UsbTransferStatusAborted; + DEBUG ((DEBUG_INFO, "Flush FIFO!!!\n" )); + EpInfo.EpNum =3D 0; + EpInfo.EpDir =3DUsbEpDirIn; + UsbXdciCoreFlushEpFifo(XdciCorePtr, &EpInfo); + EpInfo.EpNum =3D 0; + EpInfo.EpDir =3DUsbEpDirOut; + UsbXdciCoreFlushEpFifo(XdciCorePtr, &EpInfo); + DevStatus =3D UsbDeviceEp0RxSetup (UsbDeviceCorePtr, XdciCorePtr->= AlignedSetupBuffer); + } + + break; + + case DWC_XDCI_TRB_CTRL_TYPE_STATUS2: + case DWC_XDCI_TRB_CTRL_TYPE_STATUS3: + Payload->utr.Buffer =3D (VOID*) UsbFuncIoDevPtr->EndPointXferRec[End= PointNum].XferAddress; + Payload->utr.BytesTransferred =3D 0; + Payload->utr.EndpointIndex =3D (UINT8)(EndPointNum >> 1); + if ((EndPointNum & 0x01) =3D=3D 0) { + *Message =3D EfiUsbMsgEndpointStatusChangedRx; + } else { + *Message =3D EfiUsbMsgEndpointStatusChangedTx; + } + + if (TrbSts =3D=3D 0) { + if ((Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK) =3D=3D 0) { + Payload->utr.TransferStatus =3D UsbTransferStatusComplete; + } else { + Payload->utr.TransferStatus =3D UsbTransferStatusActive; + } + } else if (TrbSts !=3D 0) { + Payload->utr.TransferStatus =3D UsbTransferStatusAborted; + } + + DevStatus =3D UsbDeviceEp0RxSetup (UsbDeviceCorePtr, XdciCorePtr->Al= ignedSetupBuffer); + + if (DevStatus) { + DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: FAILED to que= ue SETUP\n")); + } + DEBUG ((DEBUG_INFO, "Status phase done. Queue next SETUP packet=3D= =3D>\n")); + break; + + default: + *Message =3D EfiUsbMsgNone; + DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: UNHANDLED STATE= in TRB\n")); + break; + } + return EFI_SUCCESS; +} + + +EFI_STATUS +NoneEp0XferDone( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT32 EndPointNum, + OUT EFI_USBFN_MESSAGE *Message, + IN OUT UINTN *PayloadSize, + OUT EFI_USBFN_MESSAGE_PAYLOAD *Payload + ) +{ + USB_DEV_CORE *UsbDeviceCorePtr; + XDCI_CORE_HANDLE *XdciCorePtr; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + DWC_XDCI_ENDPOINT *EpHandle; + DWC_XDCI_TRB *Trb; + UINT32 TrbCtrl; + UINT32 TrbSts; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + EpHandle =3D &XdciCorePtr->EpHandles[EndPointNum]; + Trb =3D XdciCorePtr->Trbs + (EndPointNum * DWC_XDCI_TRB_NUM); + + if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) { + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "NoneEp0XferDone. HW owns TRB: %x!!!, = EndPointNum: %x\n", (UINT32)(UINTN)Trb, EndPointNum)); + } + + DEBUG ((USB_FUIO_DEBUG_EVENT_D, " TRB: Addr 0x%08x!!!\n", (UINTN)Trb)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Xfer done Trb->BuffPtrLow: %x!!!\n", (= UINT32)Trb->BuffPtrLow)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Xfer done Trb->BuffPtrHigh: %x!!!\n", = (UINT32)Trb->BuffPtrHigh)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Xfer done Trb->LenXferParams: %x!!!\n"= , (UINT32)Trb->LenXferParams)); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Xfer done Trb->TrbCtrl: %x!!!\n", (UIN= T32)Trb->TrbCtrl)); + + // + // Set CheckFlag to FALSE for 'DwcXdciEpRxData' function + // check the RX request complete and continue next transfer request + // + EpHandle->CheckFlag =3D FALSE; + EpHandle->CurrentXferRscIdx =3D 0; + *Message =3D EfiUsbMsgNone; + + TrbCtrl =3D (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_TYPE_MASK) >> DWC_XDCI_TRB= _CTRL_TYPE_BIT_POS; + TrbSts =3D (Trb->LenXferParams & DWC_XDCI_TRB_STATUS_MASK) >> DWC_XDCI_T= RB_STATUS_BIT_POS; + + Payload->utr.BytesTransferred =3D UsbFuncIoDevPtr->EndPointXferRec[EndPo= intNum].XferLength; + Payload->utr.EndpointIndex =3D UsbFuncIoDevPtr->EndPointXferRec[EndPoint= Num].LogEpNum; + Payload->utr.Direction =3D UsbFuncIoDevPtr->EndPointXferRec[EndPointNum]= .Direction; + Payload->utr.Buffer =3D (VOID*)(UINTN)(Trb->BuffPtrLow); + UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].Complete =3D TRUE; + + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "EndPointAddress =3D 0x%08x\n", Payload-= >utr.EndpointIndex)); + if (Payload->utr.Direction =3D=3D EfiUsbEndpointDirectionDeviceTx) { + DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Direction::EfiUsbEndpointDirectionDe= viceTx\n")); + *Message =3D EfiUsbMsgEndpointStatusChangedTx; + } else { + DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Direction::EfiUsbEndpointDirectionDe= viceRx\n")); + *Message =3D EfiUsbMsgEndpointStatusChangedRx; + } + + if (TrbSts =3D=3D 0) { + if ((Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK) =3D=3D 0) { + Payload->utr.TransferStatus =3D UsbTransferStatusComplete; + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::UsbTransferStatusComple= te\n")); + } else { + Payload->utr.TransferStatus =3D UsbTransferStatusComplete; + Payload->utr.BytesTransferred -=3D (Trb->LenXferParams & DWC_XDCI_TR= B_BUFF_SIZE_MASK); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::UsbTransferStatusComple= te\n")); + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::Length %d \n", Payload-= >utr.BytesTransferred )); + } + } else if (TrbSts !=3D 0) { + Payload->utr.TransferStatus =3D UsbTransferStatusAborted; + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::UsbTransferStatusAborted\= n")); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +Ep0XferNotReady( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT32 EndPointNum, + OUT EFI_USBFN_MESSAGE *Message, + IN OUT UINTN *PayloadSize, + OUT EFI_USBFN_MESSAGE_PAYLOAD *Payload, + IN UINT32 EpStatus + ) +{ + USB_DEV_CORE *UsbDeviceCorePtr; + XDCI_CORE_HANDLE *XdciCorePtr; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL(This); + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + + *Message =3D EfiUsbMsgNone; + + return EFI_SUCCESS; +} + + +EFI_STATUS +EpEventCheck( + IN EFI_USBFN_IO_PROTOCOL *This, + IN USBD_EVENT_BUF *EventIndex, + OUT UINT32 *ProcessSize, + OUT EFI_USBFN_MESSAGE *Message, + IN OUT UINTN *PayloadSize, + OUT EFI_USBFN_MESSAGE_PAYLOAD *Payload, + OUT BOOLEAN *EventFlag + ) +{ + USB_DEV_CORE *UsbDeviceCorePtr; + XDCI_CORE_HANDLE *XdciCorePtr; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + UINT32 EventReg; + UINT32 EpEvent; + UINT32 EndPointNumber; + UINT32 EventStatus; + USB_EP_STATE Ep_State; + UINTN TmpBufferSize; + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV::EndPoint Event....\n")); + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL(This); + + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + EventReg =3D EventIndex->Event; + *ProcessSize =3D DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES; + *EventFlag =3D TRUE; + TmpBufferSize =3D 0; + + // + // Get EP num + // + EndPointNumber =3D (EventReg & DWC_XDCI_EVENT_BUFF_EP_NUM_MASK) >> DWC_X= DCI_EVENT_BUFF_EP_NUM_BIT_POS; + + EventStatus =3D EventReg & DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK; + + // + // Interpret event and handle transfer completion here + // + EpEvent =3D (EventReg & DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK) >> DWC_XDCI_E= VENT_BUFF_EP_EVENT_BIT_POS; + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFU_EP EventReg 0x%08x\n", EventReg))= ; + + switch (EpEvent) { + case DWC_XDCI_EVENT_BUFF_EP_XFER_CMPLT: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP DWC_XDCI_EVENT_BUFF_EP_XFE= R_CMPLT\n")); + if (EndPointNumber > 1) { + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP None_Control transfer\n"= )); + NoneEp0XferDone (This, EndPointNumber, Message, PayloadSize, Paylo= ad); + } else { + // + // Control transfer + // + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP Control transfer\n")); + Ep0XferDone (This, EndPointNumber, Message, PayloadSize, Payload); + } + break; + + case DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_READY: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_REA= DY\n")); + *Message =3D EfiUsbMsgNone; + if(EndPointNumber < (sizeof(UsbFuncIoDevPtr->EndPointXferRec) / size= of(UsbFuncIoDevPtr->EndPointXferRec[0]))) { + if ((UsbFuncIoDevPtr->EndPointXferRec[EndPointNumber].ZlpFlag =3D= =3D TRUE) && \ + (UsbFuncIoDevPtr->EndPointXferRec[EndPointNumber].Complete = =3D=3D TRUE)) { + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Request send ZLP\n")); + if ((EndPointNumber & 0x01) !=3D 0) { + Transfer(This, + UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc->EndpointA= ddress, + EfiUsbEndpointDirectionDeviceTx, + &TmpBufferSize, + NULL + ); + UsbFuncIoDevPtr->EndPointXferRec[EndPointNumber].ZlpFlag =3D F= ALSE; + } + + } + } else { + // + // Is it data stage or status stage + // + // Data Statge + // + Ep_State =3D USB_EP_STATE_DATA; + // + // Control transfer + // + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP Control transfer not rea= dy\n")); + Ep0XferNotReady (This, EndPointNumber, Message, PayloadSize, Paylo= ad, EventStatus); + *EventFlag =3D FALSE; + } + break; + + case DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS: + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROG= RESS\n")); + break; + + default: + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFUDwcXdciProcessEpEvent: UNKNOWN= EP event\n")); + break; + } + + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV::EndPoint Event....exit\n")); + return EFI_SUCCESS; +} + + +EFI_STATUS +ProcessIntLineEvents( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT32 EventCount, + IN UINT32 *ProceSsEvent, + OUT EFI_USBFN_MESSAGE *Message, + IN OUT UINTN *PayloadSize, + OUT EFI_USBFN_MESSAGE_PAYLOAD *Payload, + OUT BOOLEAN *EventFlag + ) +{ + USB_DEV_CORE *UsbDeviceCorePtr; + XDCI_CORE_HANDLE *XdciCorePtr; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + UINT32 CurrentEventAddr; + UINT32 ProceSsEventSize; + BOOLEAN EventReport; + BOOLEAN EpEventReport; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + CurrentEventAddr =3D (UINT32)(UINTN)(XdciCorePtr->CurrentEventBuffer); + EventReport =3D FALSE; + EpEventReport =3D FALSE; + ProceSsEventSize =3D 0; + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV:: ProcessIntLineEvents Entry\n"))= ; + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV:: XdciCorePtr->CurrentEventBuffer= 0x%08x\n", XdciCorePtr->CurrentEventBuffer)); + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV::EventCount0x%08x\n", EventCount)= ); + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV::CurrentEventAddr 0x%08x\n", Curr= entEventAddr)); + + while ((EventCount !=3D 0) && (EventReport =3D=3D FALSE)) { + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV::event0x%08x\n", XdciCorePtr->C= urrentEventBuffer->Event)); + if ((XdciCorePtr->CurrentEventBuffer->Event & DWC_XDCI_EVENT_DEV_MASK= ) !=3D 0) { + // + // Device event + // + DeviceEventCheck ( + This, + (USBD_EVENT_BUF*)(UINTN)CurrentEventAddr, + &ProceSsEventSize, + Message, + &EventReport + ); + if (EventReport =3D=3D TRUE) { + *EventFlag =3D TRUE; + } + + } else { + // + // EndPoint Event + // + EpEventCheck ( + This, + (USBD_EVENT_BUF*)(UINTN)CurrentEventAddr, + &ProceSsEventSize, + Message, + PayloadSize, + Payload, + &EpEventReport + ); + } + + if ((*Message !=3D EfiUsbMsgNone) || (EpEventReport =3D=3D TRUE)) { + EventReport =3D TRUE; + *EventFlag =3D TRUE; + } + + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: CurrentEventAddr 0x%08x :: Pr= oceSsEventSize 0x%08x\n", (UINTN)CurrentEventAddr,ProceSsEventSize)); + + EventCount -=3D ProceSsEventSize; + *ProceSsEvent +=3D ProceSsEventSize; + if ((CurrentEventAddr + ProceSsEventSize) >=3D \ + ((UINT32)(UINTN)(XdciCorePtr->AlignedEventBuffers) + + (sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)= )) { + CurrentEventAddr =3D (UINT32)(UINTN)(XdciCorePtr->AlignedEventBuffe= rs); + } else { + CurrentEventAddr +=3D ProceSsEventSize; + } + DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: CurrentEventAddr Update 0x%08x= :: ProceSsEventSize 0x%08x\n", CurrentEventAddr,ProceSsEventSize)); + + XdciCorePtr->CurrentEventBuffer =3D (DWC_XDCI_EVENT_BUFFER*)(UINTN)Cur= rentEventAddr; + } + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "FUEV:: ProcessIntLineEvents Exit\n\n"))= ; + return EFI_SUCCESS; +} + + +/** + ISR inokes Event Handler. Look at which interrupt has happened and see + if there are event handler registerd and if so fire them 1 by one. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] Message Indicates the event that initiated this + notification. + @param[in] PayloadSize On input, the size of the memory pointed b= y Payload. + On output, the amount of data returned in = Payload. + @param[in] Payload A pointer to EFI_USBFN_MESSAGE_PAYLOAD ins= tance to + return additional payload for current mess= age. + + + + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready t= o + process this request. + @retval EFI_BUFFER_TOO_SMALL Supplied Buffer not large enough to hold + the message payload. + +**/ +EFI_STATUS +EFIAPI +EventHandler( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT EFI_USBFN_MESSAGE *Message, + IN OUT UINTN *PayloadSize, + OUT EFI_USBFN_MESSAGE_PAYLOAD *Payload + ) +{ + UINT32 EventCount; + UINT32 PeventCount; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + UINT32 MaxIntNum; + UINT32 IntIndex; + USB_DEV_CORE *UsbDeviceCorePtr; + XDCI_CORE_HANDLE *XdciCorePtr; + BOOLEAN EventFlag; + EFI_TPL OriginalTpl; + + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFU_ EventHandler Entry\n")); + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + if (UsbFuncIoDevPtr->StartUpController =3D=3D FALSE) { + UsbFnInitDevice (This); + } + OriginalTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + *Message =3D EfiUsbMsgNone; + MaxIntNum =3D (UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC= _XDCI_GHWPARAMS1_REG) & + DWC_XDCI_GHWPARAMS1_NUM_INT_MASK) >> + DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS; + + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + EventFlag =3D TRUE; + + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "XdciCorePtr->MaxDevIntLines 0x%08x\n", = XdciCorePtr->MaxDevIntLines)); + EventCount =3D UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC= _XDCI_EVNTCOUNT_REG(0)); + + for (IntIndex =3D 0; IntIndex < XdciCorePtr->MaxDevIntLines ; IntIndex++= ) { + // + // Get the number of events HW has written for this + // interrupt line + // + EventCount =3D UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, D= WC_XDCI_EVNTCOUNT_REG(IntIndex)); + EventCount &=3D DWC_XDCI_EVNTCOUNT_MASK; + PeventCount =3D 0; + + // + // Process interrupt line Buffer only if count is non-zero + // + if (EventCount) { + // + // Process events in this Buffer + // + ProcessIntLineEvents ( + This, + EventCount, + &PeventCount, + Message, + PayloadSize, + Payload, + &EventFlag + ); + + // + // Write back the Processed number of events so HW decrements it fro= m current + // event count + // + UsbRegWrite ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_EVNT= COUNT_REG(IntIndex), PeventCount); + + // + // for debug + // + if (*Message !=3D EfiUsbMsgNone) { + break; + } + + if (EventFlag =3D=3D TRUE) { + break; + } + } + } + + gBS->RestoreTPL (OriginalTpl); + // + //EVENT_EXIT: + // + DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFU_ EventHandler Exit\n")); + return EFI_SUCCESS; +} + + + +/** + Copies relevant endpoint data from standard USB endpoint descriptors + to the usbEpInfo structure used by the XDCI + + @param pEpDest destination structure + @param pEpSrc source structure + + @return VOID + +**/ +VOID +UsbFnSetEpInfo ( + IN USB_EP_INFO *EpDest, + IN USB_DEVICE_ENDPOINT_INFO *EpSrc + ) +{ + EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc =3D NULL; + EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR *EpCompDesc =3D NULL; + + // + // start by clearing all data in the destination + // + SetMem (EpDest, sizeof(USB_EP_INFO), 0); + EpDesc =3D EpSrc->EndpointDesc; + EpCompDesc =3D EpSrc->EndpointCompDesc; + + if (EpDesc !=3D NULL) { + EpDest->EpNum =3D EpDesc->EndpointAddress & 0x0F; // Bits 0-3 are ep n= um + EpDest->EpDir =3D ((EpDesc->EndpointAddress & USB_ENDPOINT_DIR_IN) > 0= ) ? UsbEpDirIn : UsbEpDirOut; + DEBUG ((DEBUG_INFO, "EpDest->EpNum 0x%02x\n", EpDest->EpNum)); + DEBUG ((DEBUG_INFO, "EpDest->EpDir 0x%02x\n", EpDest->EpDir)); + EpDest->EpType =3D EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK; + EpDest->MaxPktSize =3D EpDesc->MaxPacketSize; + EpDest->Interval =3D EpDesc->Interval; + } + if (EpCompDesc !=3D NULL) { + EpDest->MaxStreams =3D EpCompDesc->Attributes & USB_EP_BULK_BM_ATTR_MA= SK; + EpDest->BurstSize =3D EpCompDesc->MaxBurst; + EpDest->Mult =3D EpCompDesc->BytesPerInterval; + } + + return; +} + + +EFI_STATUS +SetFnIoReqInfo( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT UINTN *BufferSize, + IN OUT VOID *Buffer, + IN OUT USB_XFER_REQUEST *XfIoreq + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + EFI_STATUS Status; + UINTN ReqPacket; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + Status =3D EFI_SUCCESS; + ReqPacket =3D 0; + + switch (EndpointIndex) { + case 0: // Control endpoint + XfIoreq->EpInfo.EpNum =3D 0; + XfIoreq->EpInfo.EpDir =3D Direction? UsbEpDirIn : UsbEpDirOut; + break; + + + default: + if (Direction =3D=3D EfiUsbEndpointDirectionDeviceTx) { + UsbFnSetEpInfo (&XfIoreq->EpInfo, &UsbFuncIoDevPtr->IndexPtrInEp); + } else { + UsbFnSetEpInfo (&XfIoreq->EpInfo, &UsbFuncIoDevPtr->IndexPtrOutEp)= ; + // + // reference from "UsbDeviceMode.c", function UsbdEpRxData + // + + // + // Transfer length should be multiple of USB packet size. + // + ReqPacket =3D *BufferSize/ XfIoreq->EpInfo.MaxPktSize; + ReqPacket =3D ((XfIoreq->XferLen % XfIoreq->EpInfo.MaxPktSize) =3D= =3D 0)? ReqPacket : ReqPacket + 1; + XfIoreq->XferLen =3D (UINT32)ReqPacket * XfIoreq->EpInfo.MaxPktSiz= e; + + } + break; + } + + if (EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + XfIoreq->XferBuffer =3D Buffer; + XfIoreq->XferLen =3D (UINT32)(*BufferSize); + XfIoreq->XferDone =3D NULL; + + return EFI_SUCCESS; +} + + +/** + Primary function to handle transfer in either direction Based on specifi= ed + direction and on the specified endpoint. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] EndpointIndex Indicates the endpoint on which TX or RX t= ransfer + needs to take place. + @param[in] Direction Direction of the endpoint. + @param[in] BufferSize If Direction is EfiUsbEndpointDirectionDev= iceRx: + On input, the size of the Buffer in bytes. + On output, the amount of data returned in = Buffer in bytes. + If Direction is EfiUsbEndpointDirectionDev= iceTx: + On input, the size of the Buffer in bytes. + On output, the amount of data actually tra= nsmitted in bytes. + @param[in] Buffer If Direction is EfiUsbEndpointDirectionDev= iceRx: + The Buffer to return the received data. + If Direction is EfiUsbEndpointDirectionDev= iceTx: + The Buffer that contains the data to be tr= ansmitted. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_NOT_READY The physical device is busy or not ready t= o + process this request. + +**/ +EFI_STATUS +EFIAPI +Transfer ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT UINTN *BufferSize, + IN OUT VOID *Buffer + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + USB_DEV_CORE *UsbDeviceCorePtr; + XDCI_CORE_HANDLE *XdciCorePtr; + EFI_STATUS Status; + USB_XFER_REQUEST XferReq; + UINT32 EndPoint; + + DEBUG ((USB_FUIO_DEBUG_LOAD, "\n FU:Transfer - Entry\n")); + DEBUG ((USB_FUIO_DEBUG_LOAD, "\n FU:EndpointIndex 0x%02x\n", EndpointInd= ex)); + DEBUG ((USB_FUIO_DEBUG_LOAD, "\n FU:Direction 0x%02x\n", Direction)); + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + UsbDeviceCorePtr =3D UsbFuncIoDevPtr->DrvCore; + XdciCorePtr =3D UsbDeviceCorePtr->ControllerHandle; + EndPoint =3D UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn = : UsbEpDirOut); + + Status =3D SetFnIoReqInfo ( + This, + EndpointIndex, + Direction, + BufferSize, + Buffer, + &XferReq + ); + + if (EFI_ERROR(Status)) { + DEBUG ((USB_FUIO_DEBUG_LOAD, "Set SetFnIoReqInfo - Error Stop!!!\n")); + while(1); + Status =3D EFI_DEVICE_ERROR; + goto FUN_EXIT; + } + + UsbFuncIoDevPtr->EndPointXferRec[EndPoint].EpNum =3D EndPoint; + UsbFuncIoDevPtr->EndPointXferRec[EndPoint].Direction =3D Direction; + UsbFuncIoDevPtr->EndPointXferRec[EndPoint].XferAddress =3D (UINTN)Buffer= ; + UsbFuncIoDevPtr->EndPointXferRec[EndPoint].XferLength =3D (UINT32)(*Buff= erSize); + UsbFuncIoDevPtr->EndPointXferRec[EndPoint].LogEpNum =3D EndpointIndex; + UsbFuncIoDevPtr->EndPointXferRec[EndPoint].Complete =3D FALSE; + UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag =3D FALSE; + + Status =3D EFI_DEVICE_ERROR; + switch (EndpointIndex) { + case 0: // Control endpoint + if (*BufferSize =3D=3D 0) { + if (Direction =3D=3D EfiUsbEndpointDirectionDeviceTx) { + Status =3D UsbDeviceEp0TxStatus(UsbDeviceCorePtr); + } else { + Status =3D UsbDeviceEp0RxStatus(UsbDeviceCorePtr); + } + } else if (Direction =3D=3D EfiUsbEndpointDirectionDeviceTx) { + Status =3D UsbXdciDeviceEpTxData(UsbDeviceCorePtr, &XferReq); + } else if (Direction =3D=3D EfiUsbEndpointDirectionDeviceRx) { + DEBUG ((USB_FUIO_DEBUG_LOAD, "\n Set Setup Package - ??? Stop!!!\n= ")); + } + break; + + default: + Status =3D EFI_SUCCESS; + if (Direction =3D=3D EfiUsbEndpointDirectionDeviceTx) { + DEBUG ((USB_FUIO_DEBUG_LOAD, "\n EfiUsbEndpointDirectionDeviceTx S= ize =3D %d\n",(*BufferSize) )); + XferReq.Zlp =3D TRUE; + if ((((*BufferSize) % 512) =3D=3D 0) && ((*BufferSize) !=3D 0)) { + UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag =3D TRUE; + DEBUG ((USB_FUIO_DEBUG_LOAD, "\n Set Zlp flag\n")); + } + Status =3D UsbXdciDeviceEpTxData (UsbDeviceCorePtr, &XferReq); + } else { + DEBUG ((USB_FUIO_DEBUG_LOAD, "\n EfiUsbEndpointDirectionDeviceRx S= ize =3D %d\n",(*BufferSize) )); + Status =3D UsbXdciDeviceEpRxData (UsbDeviceCorePtr, &XferReq); + } + break; + } + + if (EFI_ERROR(Status)) { + goto FUN_EXIT; + } + + if (Status !=3D EFI_SUCCESS) { + Status =3D EFI_DEVICE_ERROR; + } + +FUN_EXIT: + + DEBUG ((USB_FUIO_DEBUG_LOAD, "FU:Transfer - Exit %r\n", Status)); + return Status; +} + + +/** + This function supplies power to the USB controller if needed, initialize + hardware and internal data structures, and then return. + The port must not be activated by this function. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. +**/ +EFI_STATUS +EFIAPI +StartXdciController ( + IN EFI_USBFN_IO_PROTOCOL *This + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + USB_DEV_CONFIG_PARAMS ConfigParams; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + if (UsbFuncIoDevPtr->StartUpController =3D=3D TRUE) { + goto EXIT_START_CONTROLLER; + } + + ConfigParams.ControllerId =3D USB_ID_DWC_XDCI; + ConfigParams.BaseAddress =3D (UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr; + ConfigParams.Role =3D USB_ROLE_DEVICE; + ConfigParams.Speed =3D USB_SPEED_HIGH; + + // + //*Vid =3D 0x8086 + //*Pid =3D 0x0A65 + // + UsbFuncIoDevPtr->VendorId =3D USBFU_VID; + UsbFuncIoDevPtr->DeviceId =3D USBFU_PID; + UsbFuncIoDevPtr->StartUpController =3D TRUE; + + Status =3D UsbDeviceInit (&ConfigParams, &UsbFuncIoDevPtr->DrvCore); + if (Status !=3D EFI_SUCCESS) { + Status =3D EFI_DEVICE_ERROR; + goto EXIT_START_CONTROLLER; + } + + UsbFuncIoDevPtr->XdciDrvIfHandle =3D UsbFuncIoDevPtr->DrvCore->Controlle= rHandle; + +EXIT_START_CONTROLLER: + + DEBUG ((USB_FUIO_DEBUG_LOAD, "StartXdciController - Exit :: %r\n", Statu= s)); + return Status; +} + + +/** + This function disables the hardware device by resetting the run/stop bit + and power off the USB controller if needed. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. +**/ +EFI_STATUS +EFIAPI +StopXdciController ( + IN EFI_USBFN_IO_PROTOCOL *This + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + EFI_STATUS DevStatus; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + DEBUG ((USB_FUIO_DEBUG_LOAD, "StopController - Entry\n")); + + if (UsbFuncIoDevPtr->StartUpController =3D=3D FALSE) { + DEBUG ((USB_FUIO_DEBUG_LOAD, "The Controller not yet start up skip dei= nit\n")); + return EFI_SUCCESS; + } + + if (This =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + DevStatus =3D UsbDeviceDeinit (UsbFuncIoDevPtr->DrvCore, TRUE); + + UsbFuncIoDevPtr->DrvCore =3D NULL; + UsbFuncIoDevPtr->XdciDrvIfHandle =3D NULL; + UsbFuncIoDevPtr->StartUpController =3D FALSE; + + if (DevStatus !=3D EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + DEBUG ((USB_FUIO_DEBUG_LOAD, "StopController - Exit\n")); + return EFI_SUCCESS; +} + + +/** + This function sets the configuration policy for the specified non-contro= l endpoint. + Refer to the description for calling restrictions + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] EndpointIndex Indicates the non-control endpoint for + which the policy needs to be set. + @param[in] Direction Direction of the endpoint. + @param[in] PolicyType Policy type the user is trying to set for + the specified non-control endpoint. + @param[in] BufferSize The size of the Buffer in bytes. + @param[in] Buffer The new value for the policy parameter tha= t + PolicyType specifies. + + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_UNSUPPORTED Changing this policy value is not supporte= d. + +**/ +EFI_STATUS +EFIAPI +SetEndpointPolicy ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN EFI_USBFN_POLICY_TYPE PolicyType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + EFI_STATUS Status; + UINT32 EndPoint; + UINT8 *FlagPtr; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + FlagPtr =3D NULL; + + switch (PolicyType) { + case EfiUsbPolicyUndefined: + case EfiUsbPolicyMaxTransactionSize: + case EfiUsbPolicyZeroLengthTerminationSupport: + + Status =3D EFI_UNSUPPORTED; + break; + + default: + FlagPtr =3D Buffer; + Status =3D EFI_SUCCESS; + break; + } + + if (BufferSize < 1) { + Status =3D EFI_INVALID_PARAMETER; + } + + if (EFI_ERROR(Status)) { + DEBUG ((USB_FUIO_DEBUG_LOAD, "SetEndpointPolicy - ERROR %r\n", Status)= ); + return Status; + } + + EndPoint =3D UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn = : UsbEpDirOut); + + UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag =3D *FlagPtr; + + return Status; +} + + +/** + This function retrieves the configuration policy for the specified non-c= ontrol + endpoint. There are no associated calling restrictions for this function= . + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] EndpointIndex Indicates the non-control endpoint for + which the policy needs to be set. + @param[in] Direction Direction of the endpoint. + @param[in] PolicyType Policy type the user is trying to set for + the specified non-control endpoint. + @param[in] BufferSize The size of the Buffer in bytes. + @param[in] Buffer The new value for the policy parameter tha= t + PolicyType specifies. + + + @retval EFI_SUCCESS The function returned successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_DEVICE_ERROR The physical device reported an error. + @retval EFI_UNSUPPORTED Changing this policy value is not supporte= d. + @retval EFI_BUFFER_TOO_SMALL Supplied Buffer is not large enough to + hold requested policy value. + +**/ +EFI_STATUS +EFIAPI +GetEndpointPolicy ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN EFI_USBFN_POLICY_TYPE PolicyType, + IN OUT UINTN *BufferSize, + IN OUT VOID *Buffer + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + EFI_STATUS Status; + UINT32 EndPoint; + UINT32 MaxPacketSize; + BOOLEAN SetFlag; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + MaxPacketSize =3D 0; + SetFlag =3D FALSE; + + switch (PolicyType) { + case EfiUsbPolicyUndefined: + + Status =3D EFI_UNSUPPORTED; + break; + + case EfiUsbPolicyMaxTransactionSize: + case EfiUsbPolicyZeroLengthTerminationSupport: + default: + if (Buffer =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + } else { + Status =3D EFI_SUCCESS; + } + break; + } + + EndPoint =3D UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn = : UsbEpDirOut); + + if (EFI_ERROR(Status)) { + DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointPolicy - ERROR %r\n", Status)= ); + return Status; + } + + if (PolicyType =3D=3D EfiUsbPolicyMaxTransactionSize) { + + if (*BufferSize < sizeof(UINT32)) { + Status =3D EFI_INVALID_PARAMETER; + } else { + MaxPacketSize =3D MAX_TRANSFER_PACKET; + CopyMem (Buffer, &MaxPacketSize, sizeof(UINT32)); + } + + } else if (PolicyType =3D=3D EfiUsbPolicyZeroLengthTerminationSupport) { + if (*BufferSize < sizeof(BOOLEAN)) { + Status =3D EFI_INVALID_PARAMETER; + } else { + SetFlag =3D TRUE; + CopyMem (Buffer, &SetFlag, sizeof(BOOLEAN)); + } + + } else if (PolicyType =3D=3D EfiUsbPolicyZeroLengthTermination) { + if (*BufferSize < sizeof(BOOLEAN)) { + Status =3D EFI_INVALID_PARAMETER; + } else { + SetFlag =3D UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag; + CopyMem (Buffer, &SetFlag, sizeof(BOOLEAN)); + } + } else { + Status =3D EFI_INVALID_PARAMETER; + } + + return Status; +} + +EFI_STATUS +UsbFnInitDevice ( + IN EFI_USBFN_IO_PROTOCOL *This + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + + Status =3D EFI_SUCCESS; + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + PlatformSpecificInit (); + + UsbFuncIoDevPtr->StartUpController =3D FALSE; + Status =3D StartXdciController (&UsbFuncIoDevPtr->UsbFunIoProtocol); + if (EFI_ERROR (Status)) { + Status =3D EFI_DEVICE_ERROR; + goto DEV_INIT_EXIT; + } + + Status =3D UsbXdciDeviceConnect (UsbFuncIoDevPtr->DrvCore); + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbXdciDeviceConnect Status %x\n", Status)= ); + if (Status !=3D EFI_SUCCESS) { + Status =3D EFI_DEVICE_ERROR; + goto DEV_INIT_EXIT; + } + + +DEV_INIT_EXIT: + + return Status; +} + +EFI_STATUS +StartController ( + IN EFI_USBFN_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + + +EFI_STATUS +UsbFnDeInitDevice ( + IN EFI_USBFN_IO_PROTOCOL *This + ) +{ + EFI_STATUS Status; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + if (UsbFuncIoDevPtr->StartUpController =3D=3D FALSE) { + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbFn:StopController:The Controller not = yet start up force return EFI_SUCCESS\n")); + return EFI_SUCCESS; + } + + // + // disconnect + // + Status =3D UsbDeviceDisconnect (UsbFuncIoDevPtr->DrvCore); + DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbDeviceDisconnect Status %x\n", Status))= ; + if (Status !=3D EFI_SUCCESS) { + Status =3D EFI_DEVICE_ERROR; + goto DEV_DEINIT_EXIT; + } + + // + // StopController + // + Status =3D StopXdciController (&UsbFuncIoDevPtr->UsbFunIoProtocol); + UsbFuncIoDevPtr->StartUpController =3D FALSE; + +DEV_DEINIT_EXIT: + return Status; +} + +EFI_STATUS +StopController ( + IN EFI_USBFN_IO_PROTOCOL *This + ) +{ + return UsbFnDeInitDevice(This); +} + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFu= ncIo.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFuncIo= .h new file mode 100644 index 0000000..711be07 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFuncIo.h @@ -0,0 +1,234 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef __EFI_USB_FUNCTION_IO_INTERFACE_H__ +#define __EFI_USB_FUNCTION_IO_INTERFACE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "UsbIoNode.h" +#include "XdciDWC.h" +#include "UsbDeviceMode.h" + +// +// Debug message setting +// +#define USB_FUIO_DEBUG_INFO EFI_D_INFO +#define USB_FUIO_DEBUG_LOAD EFI_D_LOAD +#define USB_FUIO_DEBUG_ERROR EFI_D_ERROR +#define USB_FUIO_DEBUG_EVENT_I 0 //DEBUG_INIT +#define USB_FUIO_DEBUG_EVENT_D EFI_D_ERROR +#define USB_FUIO_DEBUG_EVENT_NOTREADY_D EFI_D_ERROR +#define USB_FUIO_DEBUG_EVENT_NOTREADY_I 0 //DEBUG_INIT + +#define MAX_TRANSFER_PACKET (8 * 1024 * 1024) + +#define USBFU_VID 0x8086 +#define USBFU_PID 0x0A65 + +#pragma pack(1) +typedef struct { + UINT8 ProgInterface; + UINT8 SubClassCode; + UINT8 BaseCode; +} USB_CLASSC; + +// +// Event Buffer Struct +// +typedef struct { + UINT32 Event; + UINT32 DevTstLmp1; + UINT32 DevTstLmp2; + UINT32 Reserved; +} USBD_EVENT_BUF; + +typedef struct { + UINT32 EpNum; + EFI_USBFN_ENDPOINT_DIRECTION Direction; + UINTN XferAddress; + UINT32 XferLength; + UINT8 LogEpNum; + BOOLEAN Complete; + BOOLEAN ZlpFlag; +} USBD_EP_XFER_REC; + +#pragma pack() + +EFI_STATUS +UsbFnInitDevice ( + IN EFI_USBFN_IO_PROTOCOL *This + ); + +EFI_STATUS +UsbFnDeInitDevice ( + IN EFI_USBFN_IO_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +DetectPort ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT EFI_USBFN_PORT_TYPE *PortType + ); + +EFI_STATUS +EFIAPI +AllocateTransferBuffer ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINTN Size, + OUT VOID **Buffer + ); + +EFI_STATUS +EFIAPI +FreeTransferBuffer ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN VOID *Buffer + ); + +EFI_STATUS +EFIAPI +ConfigureEnableEndpoints ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USB_DEVICE_INFO *DeviceInfo + ); + +EFI_STATUS +EFIAPI +GetEndpointMaxPacketSize ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USB_ENDPOINT_TYPE EndpointType, + IN EFI_USB_BUS_SPEED BusSpeed, + OUT UINT16 *MaxPacketSize + ); + +EFI_STATUS +EFIAPI +GetMaxTransferSize ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT UINTN *MaxTransferSize + ); + +EFI_STATUS +EFIAPI +GetDeviceInfo ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USBFN_DEVICE_INFO_ID Id, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer OPTIONAL + ); + +EFI_STATUS +EFIAPI +GetVendorIdProductId ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT UINT16 *Vid, + OUT UINT16 *Pid + ); + +EFI_STATUS +EFIAPI +AbortTransfer ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction + ); + +EFI_STATUS +EFIAPI +GetEndpointStallState ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT BOOLEAN *State + ); + +EFI_STATUS +EFIAPI +SetEndpointStallState ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN BOOLEAN State + ); + +EFI_STATUS +EFIAPI +EventHandler ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT EFI_USBFN_MESSAGE *Message, + IN OUT UINTN *PayloadSize, + OUT EFI_USBFN_MESSAGE_PAYLOAD *Payload + ); + +EFI_STATUS +EFIAPI +Transfer ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT UINTN *BufferSize, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +StartController ( + IN EFI_USBFN_IO_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +StopController ( + IN EFI_USBFN_IO_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +SetEndpointPolicy ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN EFI_USBFN_POLICY_TYPE PolicyType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +EFI_STATUS +EFIAPI +GetEndpointPolicy ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN EFI_USBFN_POLICY_TYPE PolicyType, + IN OUT UINTN *BufferSize, + IN OUT VOID *Buffer + ); + +VOID +UsbFnSetEpInfo ( + IN USB_EP_INFO *EpDest, + IN USB_DEVICE_ENDPOINT_INFO *EpSrc + ); + +extern EFI_USBFN_IO_PROTOCOL mUsbFunIoProtocol; +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIo= Node.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIoNode= .c new file mode 100644 index 0000000..c51ced5 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIoNode.c @@ -0,0 +1,177 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "UsbDeviceDxe.h" + + +/** + The SearchNode function search a memory address for record the driver al= locate + memory region and the node to the head link list. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] Buffer The driver alocate memory address. + @param[out] Node The match node record of the driver alooca= te + memory region. + @param[out] PNode The pervious match node record of the driv= er + aloocate memory region. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_FOUND The memory Buffer didn't find. +**/ +EFI_STATUS +SearchNode ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN VOID *Buffer, + OUT USB_MEM_NODE **Node, + OUT USB_MEM_NODE **PNode + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + USB_MEM_NODE *NodeL; + USB_MEM_NODE *PNodeL; + EFI_STATUS Status; + + DEBUG ((USB_DEBUG_MEM_NODE_INFO, "SearchNode - Entry\n")); + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL(This); + NodeL =3D UsbFuncIoDevPtr->FirstNodePtr; + PNodeL =3D NULL; + Status =3D EFI_NOT_FOUND; + + while (Node !=3D NULL) { + if (NodeL->AllocatePtr =3D=3D Buffer) { + break; + } + + PNodeL =3D NodeL; + NodeL =3D NodeL->NextPtr; + } + + if (NodeL !=3D NULL && Node !=3D NULL) { + *Node =3D NodeL; + *PNode =3D PNodeL; + Status =3D EFI_SUCCESS; + } + + DEBUG ((USB_DEBUG_MEM_NODE_INFO, "SearchNode - Exit %r\n", Status)); + return Status; +} + +/** + The InsertNewNodeToHead function remove a memory for record the driver a= llocate + memory region and the node to the head link list. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] Buffer The driver alocate memory address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_FOUND The memory Buffer didn't find. +**/ +EFI_STATUS +RemoveNode ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN VOID *Buffer + ) +{ + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + USB_MEM_NODE *Node; + USB_MEM_NODE *PNode; + EFI_STATUS Status; + + DEBUG ((USB_DEBUG_MEM_NODE_INFO, "RemoveNode - Entry\n")); + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL (This); + + Status =3D SearchNode (This, Buffer, &Node, &PNode); + + if (EFI_ERROR(Status) || PNode =3D=3D NULL) { + DEBUG ((USB_DEBUG_MEM_NODE_ERROR, "RemoveNode - Node Not Found\n")); + return EFI_NOT_FOUND; + } + + if (Node !=3D UsbFuncIoDevPtr->FirstNodePtr) { + PNode->NextPtr =3D Node->NextPtr; + } else { + UsbFuncIoDevPtr->FirstNodePtr =3D Node->NextPtr; + } + + FreePool (Node->AllocatePtr); + FreePool (Node); + DEBUG ((USB_DEBUG_MEM_NODE_INFO, "RemoveNode - Exit\n")); + return EFI_SUCCESS; +} + +/** + The InsertNewNodeToHead function allocates a memory for record the drive= r allocate + memory region and insert the node to the head link list. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[out] USB_MEM_NODE return the new node address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_OUT_OF_RESOURCES The requested transfer Buffer could not be= allocated. + +**/ +EFI_STATUS +InsertNewNodeToHead ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT USB_MEM_NODE **Node + ) +{ + USB_MEM_NODE *NewNodePtr; + USB_MEM_NODE *CurrentNodePtr; + USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr; + EFI_STATUS Status; + + DEBUG ((USB_DEBUG_MEM_NODE_INFO, "CreateNewNode - Entry\n")); + + if (This =3D=3D NULL) { + Status =3D EFI_INVALID_PARAMETER; + goto ErrorExit; + } + + UsbFuncIoDevPtr =3D USBFUIO_CONTEXT_FROM_PROTOCOL(This); + + // + // Create the new node + // + NewNodePtr =3D AllocateZeroPool (sizeof(USB_MEM_NODE)); + DEBUG ((USB_DEBUG_MEM_NODE_INFO, "NewNodePtr - Addr =3D 0x%08x\n",(UINTN= )NewNodePtr)); + + if (NewNodePtr =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + // + // insert the new node + // + CurrentNodePtr =3D UsbFuncIoDevPtr->FirstNodePtr; + UsbFuncIoDevPtr->FirstNodePtr =3D NewNodePtr; + + if (CurrentNodePtr !=3D NULL) { + NewNodePtr->NextPtr =3D CurrentNodePtr; + } + + *Node =3D NewNodePtr; + + DEBUG ((USB_DEBUG_MEM_NODE_INFO, "CreateNewNode - Exit\n")); + return EFI_SUCCESS; + +ErrorExit: + + DEBUG ((USB_DEBUG_MEM_NODE_ERROR, "CreateNewNode - error %r\n",Status)); + return Status; +} + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIo= Node.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIoNode= .h new file mode 100644 index 0000000..0ff569b --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIoNode.h @@ -0,0 +1,90 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef __EFI_USB_FUIO_MEM_NODE__ +#define __EFI_USB_FUIO_MEM_NODE__ + +#include +#include +#include +#include + +#define USB_DEBUG_MEM_NODE_INFO EFI_D_INIT +#define USB_DEBUG_MEM_NODE_ERROR EFI_D_ERROR + + +typedef struct { + UINTN Size; + VOID *AllocatePtr; + VOID *NextPtr; +} USB_MEM_NODE; + +/** + The SearchNode function search a memory address for record the driver al= locate + memory region and the node to the head link list. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] Buffer The driver alocate memory address. + @param[out] Node The match node record of the driver alooca= te + memory region. + @param[out] PNode The pervious match node record of the driv= er + aloocate memory region. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_FOUND The memory Buffer didn't find. +**/ +EFI_STATUS +SearchNode ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN VOID *Buffer, + OUT USB_MEM_NODE **Node, + OUT USB_MEM_NODE **PNode + ); + +/** + The InsertNewNodeToHead function remove a memory for record the driver a= llocate + memory region and the node to the head link list. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[in] Buffer The driver alocate memory address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_FOUND The memory Buffer didn't find. +**/ +EFI_STATUS +RemoveNode ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN VOID *Buffer + ); + +/** + The InsertNewNodeToHead function allocates a memory for record the drive= r allocate + memory region and insert the node to the head link list. + + @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL ins= tance. + @param[out] USB_MEM_NODE return the new node address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_OUT_OF_RESOURCES The requested transfer Buffer could not be= allocated. + +**/ +EFI_STATUS +InsertNewNodeToHead ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT USB_MEM_NODE **Node + ); + + #endif + + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciC= ommon.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciComm= on.h new file mode 100644 index 0000000..468e8a8 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciCommon.h @@ -0,0 +1,156 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef _XDCI_COMMON_H_ +#define _XDCI_COMMON_H_ + +#define USB_SETUP_DATA_PHASE_DIRECTION_MASK (0x80) + +// +// EP direction +// +typedef enum { + UsbEpDirOut =3D 0, + UsbEpDirIn =3D 1 +} USB_EP_DIR; + +// +// USB Speeds +// +typedef enum { + USB_SPEED_HIGH =3D 0, + USB_SPEED_FULL, + USB_SPEED_LOW, + USB_SPEED_SUPER =3D 4 +} USB_SPEED; + +typedef enum { + USB_ID_DWC_XDCI =3D 0, + USB_CORE_ID_MAX +} USB_CONTROLLER_ID; + +typedef enum { + USB_ROLE_HOST =3D 1, + USB_ROLE_DEVICE, + USB_ROLE_OTG +} USB_ROLE; + +typedef enum { + USB_XFER_QUEUED =3D 0, + USB_XFER_SUCCESSFUL, + USB_XFER_STALL +} USB_XFER_STATUS; + +typedef enum { + USB_DEVICE_DISCONNECT_EVENT =3D 0, + USB_DEVICE_RESET_EVENT, + USB_DEVICE_CONNECTION_DONE, + USB_DEVICE_STATE_CHANGE_EVENT, + USB_DEVICE_WAKEUP_EVENT, + USB_DEVICE_HIBERNATION_REQ_EVENT, + USB_DEVICE_SOF_EVENT =3D 7, + USB_DEVICE_ERRATIC_ERR_EVENT =3D 9, + USB_DEVICE_CMD_CMPLT_EVENT, + USB_DEVICE_BUFF_OVERFLOW_EVENT, + USB_DEVICE_TEST_LMP_RX_EVENT, + USB_DEVICE_SETUP_PKT_RECEIVED, + USB_DEVICE_XFER_NRDY, + USB_DEVICE_XFER_DONE +} USB_DEVICE_EVENT_ID; + +typedef enum { + U0 =3D 0, + U1, + U2, + U3, + SS_DIS, + RX_DET, + SS_INACT, + POLL, + RECOV, + HRESET, + CMPLY, + LPBK, + RESUME_RESET =3D 15 +} USB_DEVICE_SS_LINK_STATE; + +typedef enum { + CTRL_SETUP_PHASE, + CTRL_DATA_PHASE, + CTRL_STATUS_PHASE +} USB_CONTROL_XFER_PHASE; + +typedef enum { + USB_EP_STATE_DISABLED =3D 0, + USB_EP_STATE_ENABLED, + USB_EP_STATE_STALLED, + USB_EP_STATE_SETUP, + USB_EP_STATE_IN_DATA, + USB_EP_STATE_OUT_DATA, + USB_EP_STATE_DATA, + USB_EP_STATE_STATUS +} USB_EP_STATE; + +typedef struct { + VOID *ParentHandle; + UINT32 Hird; + UINT32 EpNum; + USB_SPEED Speed; + USB_EP_STATE EpState; + USB_EP_DIR EpDir; + UINT8 EpType; + USB_DEVICE_SS_LINK_STATE LinkState; + UINT8 *Buffer; + BOOLEAN SsEvent; +} USB_DEVICE_CALLBACK_PARAM; + +// +// USB endpoint +// +typedef struct { + UINT32 EpNum; + USB_EP_DIR EpDir; + UINT8 EpType; + UINT32 MaxPktSize; + UINT32 MaxStreams; + UINT32 BurstSize; + UINT32 Interval; + UINT32 Mult; +} USB_EP_INFO; + +// +// USB transfer request +// +typedef struct _USB_XFER_REQUEST USB_XFER_REQUEST; + +typedef +VOID +(EFIAPI *USB_XFER_DONE_CALLBACK) ( + IN VOID *XdciHndl, + IN USB_XFER_REQUEST *XferReq + ); + +struct _USB_XFER_REQUEST { + VOID *XferBuffer; // Buffer address. bus-width = aligned + UINT32 XferLen; // Requested transfer length + UINT32 ActualXferLen; // Actual transfer length at c= ompletion callback stage + UINT32 StreamId; // Stream ID. Only relevant f= or bulk streaming + UINT32 FrameNum; // Only relevant for periodic= transfer + USB_XFER_STATUS XferStatus; // Transfer status + USB_EP_INFO EpInfo; // EP info + USB_XFER_DONE_CALLBACK XferDone; // Transfer completion callba= ck + BOOLEAN Zlp; // Do zero-length transfer +}; + +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciD= WC.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.c new file mode 100644 index 0000000..47c5b80 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.c @@ -0,0 +1,4033 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "UsbDeviceMode.h" +#include "XdciInterface.h" +#include "XdciDWC.h" + +#pragma optimize ("", off) + +UINT32 +UsbRegRead ( + IN UINT32 Base, + IN UINT32 Offset + ) +{ + volatile UINT32 *addr =3D (volatile UINT32 *)(UINTN)(Base + Offset); + return *addr; +} + +VOID +UsbRegWrite ( + IN UINT32 Base, + IN UINT32 Offset, + IN UINT32 val + ) +{ + volatile UINT32 *addr =3D (volatile UINT32 *)(UINTN)(Base + Offset); + *addr =3D val; +} + + +/** + Internal utility function: + This function is used to obtain physical endpoint number + xDCI needs physical endpoint number for EP registers + We also use it to index into our EP array + Note: Certain data structures/commands use logical EP numbers + as opposed to physical endpoint numbers so one should be + careful when interpreting EP numbers + @EpNum: Logical endpoint number + @epDir: Direction for the endpoint + +**/ +STATIC +UINT32 +DwcXdciGetPhysicalEpNum ( + IN UINT32 EndpointNum, + IN USB_EP_DIR EndpointDir + ) +{ + return EndpointDir? ((EndpointNum << 1) | EndpointDir) : (EndpointNum <<= 1); +} + + +/** + Internal utility function: + This function is used to obtain the MPS for control transfers + Based on the Speed. If this is called before bus reset completes + then it returns MPS Based on desired Speed. If it is after bus + reset then MPS returned is Based on actual negotiated Speed + @CoreHandle: xDCI controller handle address + @mps: address of 32-bit variable to return the MPS + +**/ +STATIC +EFI_STATUS +DwcXdciCoreGetCtrlMps ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 *mps + ) +{ + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: INVALID handle\n"= )); + return EFI_DEVICE_ERROR; + } + + if (mps =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: INVALID parameter\n= ")); + return EFI_INVALID_PARAMETER; + } + + switch (CoreHandle->ActualSpeed) { + case USB_SPEED_HIGH: + *mps =3D DWC_XDCI_HS_CTRL_EP_MPS; + break; + case USB_SPEED_FULL: + *mps =3D DWC_XDCI_FS_CTRL_EP_MPS; + break; + case USB_SPEED_LOW: + *mps =3D DWC_XDCI_LS_CTRL_EP_MPS; + break; + case USB_SPEED_SUPER: + *mps =3D DWC_XDCI_SS_CTRL_EP_MPS; + break; + default: + *mps =3D 0; + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: UNKNOWN Speed\n")= ); + break; + } + + return EFI_SUCCESS; +} + + +/** + Internal utility function: + This function is used to initialize the parameters required + for executing endpoint command + @CoreHandle: xDCI controller handle address + @EpInfo: EP info address + @ConfigAction: Configuration action specific to EP command + @EpCmd: xDCI EP command for which parameters are initialized + @EpCmdParams: address of struct to return EP params + +**/ +STATIC +EFI_STATUS +DwcXdciCoreInitEpCmdParams ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN USB_EP_INFO *EpInfo, + IN UINT32 ConfigAction, + IN DWC_XDCI_ENDPOINT_CMD EpCmd, + IN DWC_XDCI_ENDPOINT_CMD_PARAMS *EpCmdParams + ) +{ + EFI_STATUS status =3D EFI_SUCCESS; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitEpCmdParams: INVALID handle= \n")); + return EFI_DEVICE_ERROR; + } + + // + // Reset params + // + EpCmdParams->Param0 =3D EpCmdParams->Param1 =3D EpCmdParams->Param2 =3D = 0; + + switch (EpCmd) { + case EPCMD_SET_EP_CONFIG: + // + // Issue DEPCFG command for EP + // Issue a DEPCFG (Command 1) command for endpoint + // + if (EpInfo->MaxStreams) { + EpCmdParams->Param1 =3D DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK; + } + + if (EpInfo->Interval) { + EpCmdParams->Param1 |=3D ((EpInfo->Interval-1) << DWC_XDCI_PARAM1_= SET_EP_CFG_BINTM1_BIT_POS); + } + + // + // Set EP num + // + EpCmdParams->Param1 |=3D (EpInfo->EpNum << DWC_XDCI_PARAM1_SET_EP_CF= G_EP_NUM_BIT_POS); + // + // Set EP direction + // + EpCmdParams->Param1 |=3D (EpInfo->EpDir << DWC_XDCI_PARAM1_SET_EP_CF= G_EP_DIR_BIT_POS); + // + // Set EP-specific Event enable for not ready and + // complete events + // + EpCmdParams->Param1 &=3D ~DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK; + // + // Setup the events we want enabled for this EP + // + EpCmdParams->Param1 |=3D (DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_M= ASK | + DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_IN_PRG= _MASK | + DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_CMPLT_= MASK); + + // + // We only have one interrupt line for this core. + // Set interrupt number to 0 + // + EpCmdParams->Param1 &=3D ~DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK; + + // + // Set FIFOnum =3D 0 for control EP0 + // + EpCmdParams->Param0 &=3D ~DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_MASK; + + // + // Program FIFOnum for non-EP0 EPs + // + if (EpInfo->EpNum && EpInfo->EpDir) { + EpCmdParams->Param0 |=3D (EpInfo->EpNum << DWC_XDCI_PARAM0_SET_EP_= CFG_FIFO_NUM_BIT_POS); + } + + // + // Program max packet size + // + EpCmdParams->Param0 &=3D ~DWC_XDCI_PARAM0_SET_EP_CFG_MPS_MASK; + EpCmdParams->Param0 |=3D (EpInfo->MaxPktSize << DWC_XDCI_PARAM0_SET_= EP_CFG_MPS_BIT_POS); + + // + // Set Burst size. 0 means burst size of 1 + // + EpCmdParams->Param0 &=3D ~DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_MASK; + EpCmdParams->Param0 |=3D (EpInfo->BurstSize << DWC_XDCI_PARAM0_SET_E= P_CFG_BRST_SIZE_BIT_POS); + + // + // Set EP type + // + EpCmdParams->Param0 &=3D ~DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_MASK; + EpCmdParams->Param0 |=3D (EpInfo->EpType << DWC_XDCI_PARAM0_SET_EP_C= FG_EP_TYPE_BIT_POS); + + // + // Set config action + // + EpCmdParams->Param0 &=3D ~DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MASK; + EpCmdParams->Param0 |=3D (ConfigAction << DWC_XDCI_PARAM0_SET_EP_CFG= _ACTN_BIT_POS); + break; + + case EPCMD_SET_EP_XFER_RES_CONFIG: + // Set Param0 to 1. Same for all EPs when resource + // configuration is done + // + EpCmdParams->Param0 =3D 1; + break; + + case EPCMD_END_XFER: + // + // Nothing to set. Already reset params for all cmds + // + break; + + case EPCMD_START_NEW_CONFIG: + // + // Nothing to set. Already reset params for all cmds + // + break; + + default: + status =3D EFI_INVALID_PARAMETER; + DEBUG ((DEBUG_INFO, "\nDwcXdciCoreInitEpCmdParams: INVALID Parameter= ")); + break; + } + + return status; +} + + +/** + Internal utility function: + This function is used to issue the xDCI endpoint command + @CoreHandle: xDCI controller handle address + @EpNum: Physical EP num + @EpCmd: xDCI EP command + @EpCmdParams: EP command parameters address + +**/ +STATIC +EFI_STATUS +DwcXdciCoreIssueEpCmd ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 EpNum, + IN UINT32 EpCmd, + IN DWC_XDCI_ENDPOINT_CMD_PARAMS *EpCmdParams + ) +{ + UINT32 BaseAddr; + UINT32 MaxDelayIter =3D 5000;//DWC_XDCI_MAX_DELAY_ITERATIONS; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreIssueEpCmd: INVALID handle\n"))= ; + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D CoreHandle->BaseAddress; + + // + // Set EP command parameter values + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EPCMD_PARAM2_REG(EpNum), + EpCmdParams->Param2 + ); + + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EPCMD_PARAM1_REG(EpNum), + EpCmdParams->Param1 + ); + + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EPCMD_PARAM0_REG(EpNum), + EpCmdParams->Param0 + ); + + // + // Set the command code and activate it + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EPCMD_REG(EpNum), + EpCmd | DWC_XDCI_EPCMD_CMD_ACTIVE_MASK + ); + + // + // Wait until command completes + // + do { + if (!(UsbRegRead (BaseAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCM= D_CMD_ACTIVE_MASK)) + break; + else + gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS); + } while (--MaxDelayIter); + + if (!MaxDelayIter) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreIssueEpCmd. ERROR: Failed to issue Com= mand\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Internal utility function: + This function is used to flush all FIFOs + @CoreHandle: xDCI controller handle address + +**/ +STATIC +EFI_STATUS +DwcXdciCoreFlushAllFifos ( + IN XDCI_CORE_HANDLE *CoreHandle + ) +{ + UINT32 BaseAddr; + UINT32 MaxDelayIter =3D DWC_XDCI_MAX_DELAY_ITERATIONS; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushAllFifos: INVALID handle\n= ")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D CoreHandle->BaseAddress; + + // + // Write the command to flush all FIFOs + // + UsbRegWrite( + BaseAddr, + DWC_XDCI_DGCMD_REG, + (UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_ALL_FI= FO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK) + ); + + // + // Wait until command completes + // + do { + if (!(UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_A= CTIVE_MASK)) + break; + else + gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS); + } while (--MaxDelayIter); + + if (!MaxDelayIter) { + DEBUG ((DEBUG_INFO, "Failed to issue Command\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Internal utility function: + This function is used to flush Tx FIFO specific to an endpoint + @CoreHandle: xDCI controller handle address + @EpNum: Physical EP num + +**/ +STATIC +EFI_STATUS +DwcXdciCoreFlushEpTxFifo ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 EpNum + ) +{ + UINT32 BaseAddr; + UINT32 MaxDelayIter =3D DWC_XDCI_MAX_DELAY_ITERATIONS; + UINT32 fifoNum; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushEpTxFifo: INVALID handle\n= ")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D CoreHandle->BaseAddress; + + // + // Translate to FIFOnum + // NOTE: Assuming this is a Tx EP + // + fifoNum =3D (EpNum >> 1); + + // + // TODO: Currently we are only using TxFIFO 0. Later map these + // Write the FIFO num/dir param for the generic command. + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DGCMD_PARAM_REG, + ((UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG) & ~DWC_XDCI_DGCMD_PA= RAM_TX_FIFO_NUM_MASK) | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK) + ); + + // + // Write the command to flush all FIFOs + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DGCMD_REG, + (UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SEL_FIF= O_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK) + ); + + + // + // Wait until command completes + // + do { + if (!(UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_AC= TIVE_MASK)) + break; + else + gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS); + } while (--MaxDelayIter); + + if (!MaxDelayIter) { + DEBUG ((DEBUG_INFO, "Failed to issue Command\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + + +STATIC +EFI_STATUS +DwcXdciCorePrepareOneTrb ( + IN DWC_XDCI_TRB *Trb, + IN DWC_XDCI_TRB_CONTROL TrbCtrl, + IN UINT32 LastBit, + IN UINT32 ChainBit, + IN UINT8 *BufferPtr, + IN UINT32 size + ) +{ + DEBUG ((DEBUG_INFO, "Trb is 0x%x, BufferPtr is 0x%x, size is 0x%x\n", Tr= b, BufferPtr, size)); + + Trb->BuffPtrLow =3D (UINT32)(UINTN)BufferPtr; + Trb->BuffPtrHigh =3D 0; + Trb->LenXferParams =3D size; + Trb->TrbCtrl =3D TrbCtrl << DWC_XDCI_TRB_CTRL_TYPE_BIT_POS; + + if (ChainBit) + Trb->TrbCtrl |=3D ChainBit << DWC_XDCI_TRB_CTRL_CHAIN_BUFF_BIT_POS; + + if (LastBit) + Trb->TrbCtrl |=3D LastBit << DWC_XDCI_TRB_CTRL_LST_TRB_BIT_POS; + + Trb->TrbCtrl |=3D DWC_XDCI_TRB_CTRL_IOSP_MISOCH_MASK| DWC_XDCI_TRB_CTRL_= HWO_MASK; + + DEBUG ((DEBUG_INFO, "(DwcXdciCorePrepareOneTrb) Trb->BuffPtrLow =3D 0x%x= , Trb->LenXferParams is 0x%x, Trb->TrbCtrl is 0x%x\n", + Trb->BuffPtrLow, Tr= b->LenXferParams, Trb->TrbCtrl)); + return EFI_SUCCESS; +} + + +/** + Internal utility function: + This function is used to initialize transfer request block + @CoreHandle: xDCI controller handle address + @Trb: Address of TRB to initialize + @TrbCtrl: TRB control value + @buffPtr: Transfer Buffer address + @size: Size of the transfer + +**/ +STATIC +EFI_STATUS +DwcXdciCoreInitTrb ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN DWC_XDCI_TRB *Trb, + IN DWC_XDCI_TRB_CONTROL TrbCtrl, + IN UINT8 *BufferPtr, + IN UINT32 size + ) +{ +#define ONE_TRB_SIZE (DWC_XDCI_TRB_BUFF_SIZE_MASK & 0x00F00000) + UINT8 *TrbBuffer; + UINT32 TrbCtrlLast; + UINT32 TrbCtrlChain; + UINT32 TrbIndex; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitTrb: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + if (Trb =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitTrb: INVALID handle\n")); + return EFI_INVALID_PARAMETER; + } + =20 + // + // Init TRB fields + // NOTE: Assuming we are only using 32-bit addresses + // TODO: update for 64-bit addresses + // + if (size <=3D DWC_XDCI_TRB_BUFF_SIZE_MASK) { + // + // Can transfer in one TRB + // + TrbCtrlChain =3D 0; + TrbCtrlLast =3D 1; + DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, Buf= ferPtr, size); + return EFI_SUCCESS; + } + + // + // Can't transfer in one TRB. + // Seperate it in every ONE_TRB_SIZE of TRB + // + TrbBuffer =3D BufferPtr; + TrbIndex =3D 0; + while (size > ONE_TRB_SIZE) { + TrbCtrlChain =3D 1; + TrbCtrlLast =3D 0; + DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, Trb= Buffer, ONE_TRB_SIZE); + TrbBuffer +=3D ONE_TRB_SIZE; + size -=3D ONE_TRB_SIZE; + Trb++; + TrbIndex++; + if (TrbIndex >=3D DWC_XDCI_TRB_NUM) + return EFI_OUT_OF_RESOURCES; + } + TrbCtrlChain =3D 0; + TrbCtrlLast =3D 1; + DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, TrbBu= ffer, size); + + return EFI_SUCCESS; +} + + +/** + Internal function: + This function is used to start a SETUP phase on control endpoint + @CoreHandle: xDCI controller handle address + +**/ +STATIC +EFI_STATUS +DwcXdciCoreStartEp0SetupXfer ( + IN XDCI_CORE_HANDLE *CoreHandle + ) +{ + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + EFI_STATUS status =3D EFI_DEVICE_ERROR; + DWC_XDCI_TRB *Trb; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreStartEp0SetupXfer: INVALID hand= le\n")); + return EFI_DEVICE_ERROR; + } + + if (CoreHandle->EpHandles[0].State =3D=3D USB_EP_STATE_SETUP) { + DEBUG ((DEBUG_INFO, "EP0 was already in SETUP phase\n")); + return EFI_SUCCESS; + } + + CoreHandle->EpHandles[0].State =3D USB_EP_STATE_SETUP; + Trb =3D CoreHandle->Trbs; + DEBUG ((DEBUG_INFO, "(DwcXdciCoreStartEp0SetupXfer)\n")); + + status =3D DwcXdciCoreInitTrb ( + CoreHandle, + Trb, + TRBCTL_SETUP, + CoreHandle->AlignedSetupBuffer, + 8 + ); + + if (status) + return status; + + // + // Issue a DEPSTRTXFER for EP0 + // Reset params + // + EpCmdParams.Param0 =3D EpCmdParams.Param1 =3D EpCmdParams.Param2 =3D 0; + + // + // Init the lower re-bits for TRB address + // + EpCmdParams.Param1 =3D (UINT32)(UINTN)Trb; + + // + // Issue the command to start transfer on physical + // endpoint 0 + // + status =3D DwcXdciCoreIssueEpCmd ( + CoreHandle, + 0, + EPCMD_START_XFER, + &EpCmdParams + ); + + // + // Save new resource index for this transfer + // + CoreHandle->EpHandles[0].CurrentXferRscIdx =3D ((UsbRegRead ( + CoreHandle->BaseAddre= ss, + DWC_XDCI_EPCMD_REG(0)= ) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS + ); + + return status; +} + + +/** + Internal function: + This function is used to process the state change event + @CoreHandle: xDCI controller handle address + @event: device event dword + +**/ +STATIC +EFI_STATUS +DwcXdciProcessDeviceStateChangeEvent ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 Event + ) +{ + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceStateChangeEvent: INVA= LID handle\n")); + return EFI_DEVICE_ERROR; + } + + CoreHandle->HirdVal =3D (Event & DWC_XDCI_EVENT_BUFF_DEV_HIRD_MASK) >> D= WC_XDCI_EVENT_BUFF_DEV_HIRD_BIT_POS; + + CoreHandle->LinkState =3D ((Event & DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_M= ASK) >> DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_BIT_POS); + + if (CoreHandle->EventCallbacks.DevLinkStateCallback) { + CoreHandle->EventCallbacks.CbEventParams.ParentHandle =3D CoreHandle->= ParentHandle; + CoreHandle->EventCallbacks.CbEventParams.LinkState =3D CoreHandle->Lin= kState; + CoreHandle->EventCallbacks.CbEventParams.Hird =3D CoreHandle->HirdVal; + CoreHandle->EventCallbacks.CbEventParams.SsEvent =3D (Event & DWC_XDCI= _EVENT_BUFF_DEV_SS_EVENT_MASK) ? 1 : 0; + CoreHandle->EventCallbacks.DevLinkStateCallback (&CoreHandle->EventCal= lbacks.CbEventParams); + } + + return EFI_SUCCESS; +} + + +/** + Internal function: + This function is used to issue a command to end transfer + @CoreHandle: xDCI controller handle address + @EpNum: Physical EP num for which transfer is to be ended + +**/ +STATIC +EFI_STATUS +DwcXdciEndXfer ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 EpNum + ) +{ + EFI_STATUS status; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + UINT32 cmdParams; + DWC_XDCI_TRB *TrbPtr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciEndXfer: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + CoreHandle->EpHandles[EpNum].CheckFlag =3D FALSE; + + // + // Issue a DEPENDXFER for EP + // Reset params + // + EpCmdParams.Param0 =3D EpCmdParams.Param1 =3D EpCmdParams.Param2 =3D 0; + + cmdParams =3D ((CoreHandle->EpHandles[EpNum].CurrentXferRscIdx << DWC_XD= CI_EPCMD_RES_IDX_BIT_POS) | DWC_XDCI_EPCMD_FORCE_RM_MASK); + + if (CoreHandle->EpHandles[EpNum].CurrentXferRscIdx =3D=3D 0) { + return EFI_SUCCESS; + } + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd( + CoreHandle, + EpNum, + cmdParams | DWC_XDCI_EPCMD_END_XFER, + &EpCmdParams + ); + + if (!status) { + CoreHandle->EpHandles[EpNum].CurrentXferRscIdx =3D 0; + TrbPtr =3D CoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM); + ZeroMem (TrbPtr, DWC_XDCI_TRB_NUM * sizeof (DWC_XDCI_TRB)); + } + + return status; +} + + +/** + Internal function: + This function is used to process bus reset detection event + @CoreHandle: xDCI controller handle address + +**/ +STATIC +EFI_STATUS +DwcXdciProcessDeviceResetDet ( + IN XDCI_CORE_HANDLE *CoreHandle + ) +{ + EFI_STATUS status =3D EFI_SUCCESS; + + if (CoreHandle =3D=3D NULL) { + return EFI_DEVICE_ERROR; + } + + // + // Flush all FIFOs + // + status =3D DwcXdciCoreFlushAllFifos(CoreHandle); + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDet: Failed to flush FIF= Os\n")); + } + + // + // Start SETUP phase on EP0 + // + status =3D DwcXdciCoreStartEp0SetupXfer(CoreHandle); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDet: Failed to start SET= UP phase for EP0\n")); + return status; + } + + // + // Notify upper layer if a callback is registerd for + // this event + // + if (CoreHandle->EventCallbacks.DevBusResetCallback) { + CoreHandle->EventCallbacks.CbEventParams.ParentHandle =3D CoreHandle->= ParentHandle; + status =3D CoreHandle->EventCallbacks.DevBusResetCallback (&CoreHandle= ->EventCallbacks.CbEventParams); + } + + return status; +} + + +/** + Internal function: + This function is used to process connection done (means reset + complete) event + @CoreHandle: xDCI controller handle address + +**/ +STATIC +EFI_STATUS +DwcXdciProcessDeviceResetDone ( + IN XDCI_CORE_HANDLE *CoreHandle + ) +{ + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + UINT32 BaseAddr; + EFI_STATUS status =3D EFI_SUCCESS; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceResetDone: INVALID han= dle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D CoreHandle->BaseAddress; + CoreHandle->ActualSpeed =3D (UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG) & = DWC_XDCI_DSTS_CONN_SPEED_MASK); + DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDone CoreHandle->ActualSpe= ed is %x\n", CoreHandle->ActualSpeed)); + + // + // Program MPS Based on the negotiated Speed + // + DwcXdciCoreGetCtrlMps (CoreHandle, &CoreHandle->EpHandles[0].EpInfo.MaxP= ktSize); + DwcXdciCoreGetCtrlMps (CoreHandle, &CoreHandle->EpHandles[1].EpInfo.MaxP= ktSize); + + // + // Init DEPCFG cmd params for EP0 + // + status =3D DwcXdciCoreInitEpCmdParams ( + CoreHandle, + &CoreHandle->EpHandles[0].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + CoreHandle, + 0, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + return status; + } + + // + // Init DEPCFG cmd params for EP1 + // + status =3D DwcXdciCoreInitEpCmdParams ( + CoreHandle, + &CoreHandle->EpHandles[1].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + CoreHandle, + 1, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + // + // Put the other PHY into suspend + // + if (CoreHandle->ActualSpeed =3D=3D USB_SPEED_SUPER) { + // + // Put HS PHY to suspend + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB2PHYCFG_REG (0), + (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) | DWC_XDCI_GUSB2= PHYCFG_SUSPEND_PHY_MASK) + ); + + // + // Clear SS PHY's suspend mask + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB3PIPECTL_REG (0), + (UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) & ~DWC_XDCI_GUS= B3PIPECTL_SUSPEND_PHY_MASK) + ); + + } else { + // + // Put SS PHY to suspend + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB3PIPECTL_REG(0), + (UsbRegRead(BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) | DWC_XDCI_GUSB3= PIPECTL_SUSPEND_PHY_MASK) + ); + + // + // Clear HS PHY's suspend mask + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB2PHYCFG_REG(0), + (UsbRegRead(BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) & ~DWC_XDCI_GUSB2= PHYCFG_SUSPEND_PHY_MASK) + ); + } + + // + // Notify upper layer if callback is registered + // + if (CoreHandle->EventCallbacks.DevResetDoneCallback) { + CoreHandle->EventCallbacks.CbEventParams.ParentHandle =3D CoreHandle->= ParentHandle; + CoreHandle->EventCallbacks.CbEventParams.Speed =3D CoreHandle->ActualS= peed; + CoreHandle->EventCallbacks.DevResetDoneCallback (&CoreHandle->EventCal= lbacks.CbEventParams); + } + + return status; +} + + +/** + Internal function: + This function is used to process device event + @CoreHandle: xDCI controller handle address + @IntLineEventBuffer: event Buffer pointing to device event + @ProcessedEventSize: address of variable to save the size of + the event that was Processed + +**/ +STATIC +EFI_STATUS +DwcXdciProcessDeviceEvent ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN DWC_XDCI_EVENT_BUFFER *IntLineEventBuffer, + IN UINT32 *ProcessedEventSize + ) +{ + UINT32 event; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceEvent: INVALID handle\= n")); + return EFI_DEVICE_ERROR; + } + + // + // Extract device event + // + event =3D (IntLineEventBuffer->Event & DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK)= ; + event >>=3D DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS; + + // + // Assume default event size. Change it in switch case if + // different + // + *ProcessedEventSize =3D DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES; + + switch (event) { + case DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT\n"= )); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT\= n")); + DwcXdciProcessDeviceResetDet (CoreHandle); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT\= n")); + DwcXdciProcessDeviceResetDone (CoreHandle); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVE= NT\n")); + DwcXdciProcessDeviceStateChangeEvent (CoreHandle, IntLineEventBuffer= ->Event); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT\n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT= \n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT\n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVEN= T\n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT\= n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT\= n")); + break; + + case DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT: + DEBUG ((DEBUG_INFO, "Device DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT= \n")); + *ProcessedEventSize =3D DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES; + break; + + default: + DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceEvent: UNHANDLED device eve= nt: %x\n", event)); + break; + } + + return EFI_SUCCESS; +} + + +/** + Internal function: + This function is used to process EP not ready for + non-control endpoints + @CoreHandle: xDCI controller handle address + @EpNum: Physical endpoint number + +**/ +STATIC +EFI_STATUS +DwcXdciProcessEpXferNotReady ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 EpNum + ) +{ + // + // TODO: Not doing on-demand transfers + // Revisit if required for later use + // + return EFI_SUCCESS; +} + + +/** + Internal function: + This function is used to process EP not ready for + control endpoints + @CoreHandle: xDCI controller handle address + @EpNum: Physical endpoint number + @dataStage: EP not ready when data stage token was received + @statusStage: EP not ready when status stage token was received + +**/ +STATIC +EFI_STATUS +DwcXdciProcessEp0XferNotReady ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 EpNum, + IN UINT32 epEventStatus + ) +{ + USB_EP_STATE epState =3D USB_EP_STATE_SETUP; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEp0XferNotReady: INVALID han= dle\n")); + return EFI_DEVICE_ERROR; + } + // + // Is it data stage or status stage + // + if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_DATA_REQ_MASK) { + epState =3D USB_EP_STATE_DATA; + } else if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_STATUS_REQ_MASK) = { + epState =3D USB_EP_STATE_STATUS; + } + + if ((EpNum =3D=3D 0) && (epState =3D=3D USB_EP_STATE_STATUS)) { + if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_XFER_ACTIVE_MASK) { + DEBUG ((DEBUG_INFO, "XFER_ACTIVE\n")); + } else { + DEBUG ((DEBUG_INFO, "XFER_NOT_ACTIVE\n")); + } + DwcXdciEp0ReceiveStatusPkt (CoreHandle); + } + + // + // Notify upper layer if a callback is registered for + // this event + // + if (CoreHandle->EventCallbacks.DevXferNrdyCallback) { + CoreHandle->EventCallbacks.CbEventParams.ParentHandle =3D CoreHandle->= ParentHandle; + CoreHandle->EventCallbacks.CbEventParams.EpState =3D epState; + CoreHandle->EventCallbacks.DevXferNrdyCallback (&CoreHandle->EventCall= backs.CbEventParams); + } + + return EFI_SUCCESS; +} + + +/** + Internal function: + This function is used to process transfer phone done for EP0 + @CoreHandle: xDCI controller handle address + @EpNum: Physical endpoint number (0 for OUT and 1 for IN) + +**/ +STATIC +EFI_STATUS +DwcXdciProcessEp0XferPhaseDone ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 EpNum + ) +{ + DWC_XDCI_ENDPOINT *epHandle; + DWC_XDCI_TRB *Trb; + EFI_STATUS status =3D EFI_SUCCESS; + UINT32 TrbSts; + UINT32 TrbCtrl; + UINT32 TrbBufsize; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEp0XferPhaseDone: INVALID ha= ndle\n")); + return EFI_DEVICE_ERROR; + } + + epHandle =3D &CoreHandle->EpHandles[EpNum]; + Trb =3D CoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM); + DEBUG ((DEBUG_INFO, "(DwcXdciProcessEp0XferPhaseDone)EpNum is %d\n", EpN= um)); + + if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) { + DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone. HW owns TRB: %x!!= !\n", (UINT32)(UINTN)Trb)); + } + + epHandle->CurrentXferRscIdx =3D 0; + epHandle->State =3D USB_EP_STATE_ENABLED; + TrbCtrl =3D (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_TYPE_MASK) >> DWC_XDCI_TRB= _CTRL_TYPE_BIT_POS; + TrbSts =3D (Trb->LenXferParams & DWC_XDCI_TRB_STATUS_MASK) >> DWC_XDCI_T= RB_STATUS_BIT_POS; + TrbBufsize =3D Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK; + + switch (TrbCtrl) { + case DWC_XDCI_TRB_CTRL_TYPE_SETUP: + DEBUG ((DEBUG_INFO, "SETUP\n")); + if (CoreHandle->EventCallbacks.DevSetupPktReceivedCallback) { + CoreHandle->EventCallbacks.CbEventParams.ParentHandle =3D CoreHand= le->ParentHandle; + CoreHandle->EventCallbacks.CbEventParams.Buffer =3D CoreHandle->Al= ignedSetupBuffer; + status =3D CoreHandle->EventCallbacks.DevSetupPktReceivedCallback = (&CoreHandle->EventCallbacks.CbEventParams); + } + + if (!(CoreHandle->AlignedSetupBuffer[0] & USB_SETUP_DATA_PHASE_DIREC= TION_MASK)) { + // + // Keep a Buffer ready for setup phase + // + DwcXdciCoreStartEp0SetupXfer (CoreHandle); + } + + break; + + case DWC_XDCI_TRB_CTRL_TYPE_STATUS2: + DEBUG ((DEBUG_INFO, "STATUS2\n")); + break; + + case DWC_XDCI_TRB_CTRL_TYPE_STATUS3: + DEBUG ((DEBUG_INFO, "STATUS3\n")); + // + // Notify upper layer of control transfer completion + // if a callback function was registerd + // + if (CoreHandle->EventCallbacks.DevXferDoneCallback) { + CoreHandle->EventCallbacks.CbEventParams.ParentHandle =3D CoreHand= le->ParentHandle; + CoreHandle->EventCallbacks.CbEventParams.EpNum =3D (EpNum >> 1); + CoreHandle->EventCallbacks.CbEventParams.EpDir =3D (EpNum & 1); + CoreHandle->EventCallbacks.CbEventParams.Buffer =3D (UINT8 *)(UINT= N)(Trb->BuffPtrLow); + CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->Event= Callbacks.CbEventParams); + } + + // + // Status phase done. Queue next SETUP packet + // + status =3D DwcXdciCoreStartEp0SetupXfer(CoreHandle); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: FAILED to que= ue SETUP\n")); + } + break; + + case DWC_XDCI_TRB_CTRL_TYPE_DATA: + DEBUG ((DEBUG_INFO, "DATA\n")); + if (TrbSts =3D=3D DWC_XDCI_TRB_STATUS_SETUP_PENDING || TrbBufsize != =3D 0) { + DEBUG ((DEBUG_INFO, "ERROR: Control transfert aborted by host: Set= up pending\n")); + DwcXdciCoreStartEp0SetupXfer (CoreHandle); + } + + if (CoreHandle->EventCallbacks.DevXferDoneCallback) { + CoreHandle->EventCallbacks.CbEventParams.ParentHandle =3D CoreHand= le->ParentHandle; + CoreHandle->EventCallbacks.CbEventParams.EpNum =3D (EpNum >> 1); + CoreHandle->EventCallbacks.CbEventParams.EpDir =3D (EpNum & 1); + CoreHandle->EventCallbacks.CbEventParams.Buffer =3D (UINT8 *)(UINT= N)(Trb->BuffPtrLow); + CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->Event= Callbacks.CbEventParams); + } + break; + + default: + DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: UNHANDLED STATE= in TRB\n")); + break; + } + + return status; +} + + +/** + Internal function: + This function is used to process transfer done for + non-control endpoints + @CoreHandle: xDCI controller handle address + @EpNum: Physical endpoint number + +**/ +STATIC +EFI_STATUS +DwcXdciProcessEpXferDone ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 EpNum + ) +{ + DWC_XDCI_ENDPOINT *epHandle; + DWC_XDCI_TRB *Trb; + USB_XFER_REQUEST *XferReq; + UINT32 remainingLen; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: INVALID handle\n= ")); + return EFI_DEVICE_ERROR; + } + + epHandle =3D &CoreHandle->EpHandles[EpNum]; + epHandle->CurrentXferRscIdx =3D 0; + Trb =3D epHandle->Trb; + XferReq =3D &epHandle->XferHandle; + + // + // if transfer done, set CheckFlag to FALSE for allow next transfer requ= est. + // + epHandle->CheckFlag =3D FALSE; + + if ((Trb =3D=3D NULL) || (XferReq =3D=3D NULL)) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: INVALID paramete= r\n")); + return EFI_INVALID_PARAMETER; + } + + // + // Compute the actual transfer length + // + XferReq->ActualXferLen =3D XferReq->XferLen; + remainingLen =3D (Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK); + + if (remainingLen > XferReq->XferLen) { + // + // Buffer overrun? This should never happen + // + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: Possible Buffer = overrun\n")); + } else { + XferReq->ActualXferLen -=3D remainingLen; + } + + // + // Notify upper layer of request-specific transfer completion + // if there is a callback specifically for this request + // + if (XferReq->XferDone) { + XferReq->XferDone(CoreHandle->ParentHandle, XferReq); + } + + // + // Notify upper layer if a callback was registered + // + if (CoreHandle->EventCallbacks.DevXferDoneCallback) { + CoreHandle->EventCallbacks.CbEventParams.ParentHandle =3D CoreHandle->= ParentHandle; + CoreHandle->EventCallbacks.CbEventParams.EpNum =3D (EpNum >> 1); + CoreHandle->EventCallbacks.CbEventParams.EpDir =3D (EpNum & 1); + CoreHandle->EventCallbacks.CbEventParams.EpType =3D epHandle->EpInfo.E= pType; + CoreHandle->EventCallbacks.CbEventParams.Buffer =3D (UINT8 *)(UINTN)(e= pHandle->Trb->BuffPtrLow); + CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCall= backs.CbEventParams); + } + + return EFI_SUCCESS; +} + + +/** + Internal function: + This function is used to process endpoint events + @CoreHandle: xDCI controller handle address + @IntLineEventBuffer: address of Buffer containing event + to process + @ProcessedEventSize: address to save the size of event + Processed + +**/ +STATIC +EFI_STATUS +DwcXdciProcessEpEvent ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN DWC_XDCI_EVENT_BUFFER *IntLineEventBuffer, + IN UINT32 *ProcessedEventSize + ) +{ + UINT32 EpNum; + UINT32 epEvent; + UINT32 epEventStatus; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpEvent: INVALID handle\n"))= ; + return EFI_DEVICE_ERROR; + } + + epEvent =3D IntLineEventBuffer->Event; + + *ProcessedEventSize =3D DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES; + + // + // Get EP num + // + EpNum =3D ((epEvent & DWC_XDCI_EVENT_BUFF_EP_NUM_MASK) >> DWC_XDCI_EVENT= _BUFF_EP_NUM_BIT_POS); + epEventStatus =3D (epEvent & DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK); + + // + // Interpret event and handle transfer completion here + // + epEvent =3D ((epEvent & DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK) >> DWC_XDCI_E= VENT_BUFF_EP_EVENT_BIT_POS); + + switch (epEvent) { + case DWC_XDCI_EVENT_BUFF_EP_XFER_CMPLT: + DEBUG ((DEBUG_INFO, "XFER_CMPLT ep %d\n", EpNum)); + if (EpNum > 1) { + DwcXdciProcessEpXferDone (CoreHandle, EpNum); + } else { + DwcXdciProcessEp0XferPhaseDone (CoreHandle, EpNum); + } + break; + + case DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS: + DEBUG ((DEBUG_INFO, "IN_PROGRESS\n")); + break; + + case DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_READY: + DEBUG ((DEBUG_INFO, "NOT_READY ep %d\n", EpNum)); + if (EpNum > 1) { + // + // Endpoint transfer is not ready + // + DwcXdciProcessEpXferNotReady (CoreHandle, EpNum); + } else { + DwcXdciProcessEp0XferNotReady (CoreHandle, EpNum, epEventStatus); + } + break; + + default: + DEBUG ((DEBUG_INFO, "DwcXdciProcessEpEvent: UNKNOWN EP event\n")); + break; + } + + return EFI_SUCCESS; +} + + +/** + Internal function: + This function is used to process events on single interrupt line + @CoreHandle: xDCI controller handle address + @eventCount: event bytes to process + @ProcessedEventCount: address to save the size + (in bytes) of event Processed + Processed + +**/ +STATIC +EFI_STATUS +DwcXdciProcessInterruptLineEvents ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 eventCount, + IN UINT32 *ProcessedEventCount + ) +{ + UINT32 ProcessedEventSize =3D 0; + UINT32 currentEventAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessInterruptLineEvents: INVALID= handle\n")); + return EFI_DEVICE_ERROR; + } + + if (CoreHandle->CurrentEventBuffer =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessInterruptLineEvents: INVALID= event Buffer\n")); + return EFI_INVALID_PARAMETER; + } + + currentEventAddr =3D (UINT32)(UINTN)(CoreHandle->CurrentEventBuffer); + + // + // Process eventCount/eventSize number of events + // in this run + // + while (eventCount) { + if (CoreHandle->CurrentEventBuffer->Event & DWC_XDCI_EVENT_DEV_MASK) { + DwcXdciProcessDeviceEvent ( + CoreHandle, + CoreHandle->CurrentEventBuffer, + &ProcessedEventSize + ); + } else { + DwcXdciProcessEpEvent ( + CoreHandle, + CoreHandle->CurrentEventBuffer, + &ProcessedEventSize); + } + + eventCount -=3D ProcessedEventSize; + *ProcessedEventCount +=3D ProcessedEventSize; + if ((currentEventAddr + ProcessedEventSize) >=3D + ((UINT32)(UINTN)(CoreHandle->AlignedEventBuffers) + (sizeof(DWC_XD= CI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)) + ) { + currentEventAddr =3D (UINT32)(UINTN)(CoreHandle->AlignedEventBuffers= ); + DEBUG ((DEBUG_INFO, "DwcXdciProcessInterruptLineEvents: Event Buffer= bound reached\n")); + } else { + currentEventAddr +=3D ProcessedEventSize; + } + + CoreHandle->CurrentEventBuffer =3D (DWC_XDCI_EVENT_BUFFER *)(UINTN)cur= rentEventAddr; + } + + return EFI_SUCCESS; +} + +// +// DWC XDCI APIs +// + +/** + Interface: + + This function is used to initialize the xDCI core + @configParams: Parameters from app to configure the core + @deviceCorePtr: HW-independent APIs handle for device core + @CoreHandle: xDCI controller handle retured + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreInit ( + IN USB_DEV_CONFIG_PARAMS *ConfigParams, + IN VOID *deviceCorePtr, + IN VOID **CoreHandle + ) +{ + EFI_STATUS status =3D EFI_DEVICE_ERROR; + UINT32 BaseAddr; + XDCI_CORE_HANDLE *LocalCoreHandle; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + UINT32 MaxDelayIter =3D DWC_XDCI_MAX_DELAY_ITER= ATIONS; + UINT8 i; + + LocalCoreHandle =3D (XDCI_CORE_HANDLE *)AllocateZeroPool (sizeof(XDCI_CO= RE_HANDLE)); + + if (CoreHandle =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (LocalCoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to allocate handle for xD= CI\n")); + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (LocalCoreHandle, sizeof(XDCI_CORE_HANDLE)); + + LocalCoreHandle->ParentHandle =3D deviceCorePtr; + + *CoreHandle =3D (VOID *)LocalCoreHandle; + + LocalCoreHandle->Id =3D ConfigParams->ControllerId; + LocalCoreHandle->BaseAddress =3D BaseAddr =3D ConfigParams->BaseAddress; + LocalCoreHandle->Flags =3D ConfigParams->Flags; + LocalCoreHandle->DesiredSpeed =3D LocalCoreHandle->ActualSpeed =3D Confi= gParams->Speed; + LocalCoreHandle->Role =3D ConfigParams->Role; + + DEBUG ((DEBUG_INFO, "Resetting the USB core\n")); + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCTL_REG, + UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | DWC_XDCI_DCTL_CSFTRST_MASK + ); + // + // Wait until core soft reset completes + // + do { + if (!(UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & DWC_XDCI_DCTL_CSFTRST= _MASK)) { + break; + } else { + gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS); + } + } while (--MaxDelayIter); + + if (!MaxDelayIter) { + DEBUG ((DEBUG_INFO, "Failed to reset device controller\n")); + return EFI_DEVICE_ERROR; + } + + DEBUG ((DEBUG_INFO, "USB core has been reset\n")); + + // + // All FIFOs are flushed at this point + // + // + // Ensure we have EP0 Rx/Tx handles initialized + // + LocalCoreHandle->EpHandles[0].EpInfo.EpNum =3D 0; + LocalCoreHandle->EpHandles[0].EpInfo.EpDir =3D UsbEpDirOut; + LocalCoreHandle->EpHandles[0].EpInfo.EpType =3D USB_ENDPOINT_CONTROL; + LocalCoreHandle->EpHandles[0].EpInfo.MaxPktSize =3D DWC_XDCI_SS_CTRL_EP_= MPS; + // + // 0 means burst size of 1 + // + LocalCoreHandle->EpHandles[0].EpInfo.BurstSize =3D 0; + + LocalCoreHandle->EpHandles[1].EpInfo.EpNum =3D 0; + LocalCoreHandle->EpHandles[1].EpInfo.EpDir =3D UsbEpDirIn; + LocalCoreHandle->EpHandles[1].EpInfo.EpType =3D USB_ENDPOINT_CONTROL; + LocalCoreHandle->EpHandles[1].EpInfo.MaxPktSize =3D DWC_XDCI_SS_CTRL_EP_= MPS; + // + // 0 means burst size of 1 + // + LocalCoreHandle->EpHandles[1].EpInfo.BurstSize =3D 0; + + LocalCoreHandle->DevState =3D UsbDevStateDefault; + + // + // Clear KeepConnect bit so we can allow disconnect and + // re-connect. Stay in RX_DETECT state + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCTL_REG, + UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & + (~DWC_XDCI_DCTL_KEEP_CONNECT_MASK) & + ((~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK) | (DWC_XDCI_DCTL_STATE_CHANGE_= REQ_RX_DETECT << DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS)) + ); + + DEBUG ((DEBUG_INFO, "Device controller Synopsys ID: %x\n", UsbRegRead (B= aseAddr, DWC_XDCI_GSNPSID_REG))); + DEBUG ((DEBUG_INFO, "Default value of xDCI GSBUSCFG0 and GSBUSCFG1: %x, = %x\n", + UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG0_REG), + UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG1_REG))); + + DEBUG ((DEBUG_INFO, "Default value of xDCI GTXTHRCFG and GRXTHRCFG: %x, = %x\n", + UsbRegRead (BaseAddr, DWC_XDCI_GTXTHRCFG_REG), + UsbRegRead (BaseAddr, DWC_XDCI_GRXTHRCFG_REG))); + + // + // Clear ULPI auto-resume bit + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB2PHYCFG_REG (0), + (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)) & ~DWC_XDCI_GUSB2= PHYCFG_ULPI_AUTO_RESUME_MASK) + ); + + DEBUG ((DEBUG_INFO, "Default value of xDCI GUSB2PHYCFG and GUSB3PIPECTL:= %x, %x\n", + UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)), + UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG (0)))); + // + // Only one RxFIFO + // + DEBUG ((DEBUG_INFO, "Default value of DWC_XDCI_GRXFIFOSIZ: %x\n", + UsbRegRead (BaseAddr, DWC_XDCI_GRXFIFOSIZ_REG (0)))); + + for (i =3D 0; i < DWC_XDCI_MAX_ENDPOINTS; i++) { + DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_GTXFIFOSIZ %d: %x\= n", + i, UsbRegRead (BaseAddr, DWC_XDCI_GTXFIFOSIZ_REG (i)))); + } + + // + // TODO: Need to check if TxFIFO should start where RxFIFO ends + // or default is correct i.e. TxFIFO starts at 0 just like RxFIFO + // + + // + // Allocate and Initialize Event Buffers + // + LocalCoreHandle->MaxDevIntLines =3D ((UsbRegRead (BaseAddr, DWC_XDCI_GHW= PARAMS1_REG) & + DWC_XDCI_GHWPARAMS1_NUM_INT_MAS= K) >> + DWC_XDCI_GHWPARAMS1_NUM_INT_BIT= _POS); + + DEBUG ((DEBUG_INFO, "Max dev int lines: %d\n", LocalCoreHandle->MaxDevIn= tLines)); + // + // One event Buffer per interrupt line. + // Need to align it to size of event Buffer + // Buffer needs to be big enough. Otherwise the core + // won't operate + // + LocalCoreHandle->AlignedEventBuffers =3D (DWC_XDCI_EVENT_BUFFER *) + ((UINT32)(UINTN)(LocalCoreHan= dle->EventBuffers) + + ((sizeof (DWC_XDCI_EVENT_BUFF= ER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) - + (((UINT32)(UINTN)(LocalCoreHa= ndle->EventBuffers)) % + (sizeof (DWC_XDCI_EVENT_BUFFE= R) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)))); + + for (i =3D 0; i < LocalCoreHandle->MaxDevIntLines; i++) { + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GEVNTADR_REG (i), + (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers + i * sizeof(DW= C_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) + ); + + // + // Clear High 32bit address register, GEVNTADR register is 64-bit regi= ster + // default is 0xffffffffffffffff + // + UsbRegWrite (BaseAddr, DWC_XDCI_GEVNTADR_REG (i) + 4, 0x00000000); + + LocalCoreHandle->CurrentEventBuffer =3D LocalCoreHandle->AlignedEventB= uffers; + // + // Write size and clear the mask + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EVNTSIZ_REG (i), + sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER + ); + + // + // Write 0 to the event count register as the last step + // + // for event configuration + // + UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), 0); + + DEBUG ((DEBUG_INFO, "Value of xDCI Event Buffer %d: %x, Size: %x, Coun= t: %x\n", + i, + UsbRegRead (BaseAddr, DWC_XDCI_GEVNTADR_REG (i)), + UsbRegRead (BaseAddr, DWC_XDCI_EVNTSIZ_REG (i)), + UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i)))= ); + } + + // + // Program Global Control Register to disable scaledown, + // disable clock gating + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GCTL_REG, + ((UsbRegRead(BaseAddr, DWC_XDCI_GCTL_REG) & + ~(DWC_XDCI_GCTL_SCALE_DOWN_MODE_MASK + DWC_XDCI_GCTL_R= AMCLKSEL_MASK + DWC_XDCI_GCTL_DISABLE_SCRAMB_MASK)) | + DWC_XDCI_GCTL_DISABLE_CLK_GATING_MASK | + (DWC_XDCI_GCTL_PRT_CAP_DEVICE << DWC_XDCI_GCTL_PRT_CAP= _DIR_BIT_POS))); + + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", U= sbRegRead (BaseAddr, DWC_XDCI_GCTL_REG))); + + // + // TODO: Program desired Speed and set LPM capable + // We will do this when SuperSpeed works. For now, + // force into High-Speed mode to aVOID anyone trying this + // on Super Speed port + // +#ifdef SUPPORT_SUPER_SPEED + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCFG_REG, + (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV= _SPEED_MASK) | LocalCoreHandle->DesiredSpeed + ); +#else + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCFG_REG, + (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV= _SPEED_MASK) | DWC_XDCI_DCFG_DESIRED_HS_SPEED + ); +#endif + + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", Usb= RegRead (BaseAddr, DWC_XDCI_DCFG_REG))); + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", Usb= RegRead (BaseAddr, DWC_XDCI_DSTS_REG))); + + // + // Enable Device Interrupt Events + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DEVTEN_REG, + DWC_XDCI_DEVTEN_DEVICE_INTS + ); + // + // Program the desired role + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GCTL_REG, + (UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG) & ~DWC_XDCI_GCTL_PRT_CAP_DIR= _MASK) | (LocalCoreHandle->Role << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS) + ); + // + // Clear USB2 suspend for start new config command + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB2PHYCFG_REG (0), + (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) & ~DWC_XDCI_GUSB2P= HYCFG_SUSPEND_PHY_MASK) + ); + + // + // Clear USB3 suspend for start new config command + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB3PIPECTL_REG (0), + (UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) & ~DWC_XDCI_GUSB3= PIPECTL_SUSPEND_PHY_MASK) + ); + + // + // Issue DEPSTARTCFG command for EP0 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[0].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE, + EPCMD_START_NEW_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for START_= NEW_CONFIG EP command on xDCI\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 0, + EPCMD_START_NEW_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue START_NEW_CONFIG= EP command on xDCI\n")); + return status; + } + + // + // Issue DEPCFG command for EP0 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[0].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for SET_EP= _CONFIG command on xDCI for EP0\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 0, + EPCMD_SET_EP_CONFIG, + &EpCmdParams); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG co= mmand on xDCI for EP0\n")); + return status; + } + + // + // Issue DEPCFG command for EP1 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[1].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for SET_EP= _CONFIG command on xDCI for EP1\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 1, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG co= mmand on xDCI for EP1\n")); + return status; + } + + // + // Issue DEPXFERCFG command for EP0 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[0].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for EPCMD_= SET_EP_XFER_RES_CONFIG command on xDCI for EP0\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 0, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFE= R_RES_CONFIG command on xDCI for EP0\n")); + return status; + } + + // + // Issue DEPXFERCFG command for EP1 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[1].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for EPCMD_= SET_EP_XFER_RES_CONFIG command on xDCI for EP1\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 1, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFE= R_RES_CONFIG command on xDCI for EP1\n")); + return status; + } + + // + // Prepare a Buffer for SETUP packet + // + LocalCoreHandle->Trbs =3D (DWC_XDCI_TRB *)(UINTN)((UINT32)(UINTN) + LocalCoreHandle->UnalignedTrbs + + (DWC_XDCI_TRB_BYTE_ALIGNMENT - + ((UINT32)(UINTN)LocalCoreHandle->UnalignedTrbs= % + DWC_XDCI_TRB_BYTE_ALIGNMENT))); + + DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ unalignedTrbs address is= 0x%x\n", LocalCoreHandle->UnalignedTrbs)); + DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ TRB address is 0x%x\n", = LocalCoreHandle->Trbs)); + // + // Allocate Setup Buffer that is 8-byte aligned + // + LocalCoreHandle->AlignedSetupBuffer =3D LocalCoreHandle->DefaultSetupBuf= fer + + (DWC_XDCI_SETUP_BUFF_SIZE - + ((UINT32)(UINTN)(LocalCoreHand= le->DefaultSetupBuffer) % DWC_XDCI_SETUP_BUFF_SIZE)); + + // + // Aligned Buffer for status phase + // + LocalCoreHandle->AlignedMiscBuffer =3D LocalCoreHandle->MiscBuffer + + (DWC_XDCI_SETUP_BUFF_SIZE - + ((UINT32)(UINTN)(LocalCoreHandl= e->AlignedMiscBuffer) % DWC_XDCI_SETUP_BUFF_SIZE)); + + + // + // Enable Physical Endpoints 0 + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EP_DALEPENA_REG, + UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 0) + ); + // + // Enable Physical Endpoints 1 + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EP_DALEPENA_REG, + UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 1) + ); + + DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n",= UsbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG))); + return status; +} + + +/** + Interface: + This function is used to de-initialize the xDCI core + @CoreHandle: xDCI controller handle + @flags: Special flags for de-initializing the core in + particular way + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreDeinit ( + IN VOID *CoreHandle, + IN UINT32 flags + ) +{ + FreePool (CoreHandle); + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to register event callback function + @CoreHandle: xDCI controller handle + @event: Event for which callback is to be registered + @callbackFn: Callback function to invoke after event occurs + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreRegisterCallback ( + IN VOID *CoreHandle, + IN USB_DEVICE_EVENT_ID Event, + IN USB_DEVICE_CALLBACK_FUNC CallbackFunc + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + + if (LocalCoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreRegisterCallback: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + DEBUG ((DEBUG_INFO, "DwcXdciCoreRegisterCallback: event is %d\n", Event)= ); + switch (Event) { + case USB_DEVICE_DISCONNECT_EVENT: + LocalCoreHandle->EventCallbacks.DevDisconnectCallback =3D CallbackFu= nc; + break; + + case USB_DEVICE_RESET_EVENT: + LocalCoreHandle->EventCallbacks.DevBusResetCallback =3D CallbackFunc= ; + break; + + case USB_DEVICE_CONNECTION_DONE: + LocalCoreHandle->EventCallbacks.DevResetDoneCallback =3D CallbackFun= c; + break; + + case USB_DEVICE_STATE_CHANGE_EVENT: + LocalCoreHandle->EventCallbacks.DevLinkStateCallback =3D CallbackFun= c; + break; + + case USB_DEVICE_WAKEUP_EVENT: + LocalCoreHandle->EventCallbacks.DevWakeupCallback =3D CallbackFunc; + break; + + case USB_DEVICE_HIBERNATION_REQ_EVENT: + LocalCoreHandle->EventCallbacks.DevHibernationCallback =3D CallbackF= unc; + break; + + case USB_DEVICE_SOF_EVENT: + LocalCoreHandle->EventCallbacks.DevSofCallback =3D CallbackFunc; + break; + + case USB_DEVICE_ERRATIC_ERR_EVENT: + LocalCoreHandle->EventCallbacks.DevErraticErrCallback =3D CallbackFu= nc; + break; + + case USB_DEVICE_CMD_CMPLT_EVENT: + LocalCoreHandle->EventCallbacks.DevCmdCmpltCallback =3D CallbackFunc= ; + break; + + case USB_DEVICE_BUFF_OVERFLOW_EVENT: + LocalCoreHandle->EventCallbacks.DevBuffOvflwCallback =3D CallbackFun= c; + break; + + case USB_DEVICE_TEST_LMP_RX_EVENT: + LocalCoreHandle->EventCallbacks.DevTestLmpRxCallback =3D CallbackFun= c; + break; + + case USB_DEVICE_SETUP_PKT_RECEIVED: + LocalCoreHandle->EventCallbacks.DevSetupPktReceivedCallback =3D Call= backFunc; + break; + + case USB_DEVICE_XFER_NRDY: + LocalCoreHandle->EventCallbacks.DevXferNrdyCallback =3D CallbackFunc= ; + break; + + case USB_DEVICE_XFER_DONE: + LocalCoreHandle->EventCallbacks.DevXferDoneCallback =3D CallbackFunc= ; + break; + + default: + break; + } + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to unregister event callback function + @CoreHandle: xDCI controller handle + @event: Event for which callback function is to be unregistered + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreUnregisterCallback ( + IN VOID *CoreHandle, + IN USB_DEVICE_EVENT_ID event + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + + if (LocalCoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreUnregisterCallback: INVALID handle\n")= ); + return EFI_DEVICE_ERROR; + } + + switch (event) { + case USB_DEVICE_DISCONNECT_EVENT: + LocalCoreHandle->EventCallbacks.DevDisconnectCallback =3D NULL; + break; + + case USB_DEVICE_RESET_EVENT: + LocalCoreHandle->EventCallbacks.DevBusResetCallback =3D NULL; + break; + + case USB_DEVICE_CONNECTION_DONE: + LocalCoreHandle->EventCallbacks.DevResetDoneCallback =3D NULL; + break; + + case USB_DEVICE_STATE_CHANGE_EVENT: + LocalCoreHandle->EventCallbacks.DevLinkStateCallback =3D NULL; + break; + + case USB_DEVICE_WAKEUP_EVENT: + LocalCoreHandle->EventCallbacks.DevWakeupCallback =3D NULL; + break; + + case USB_DEVICE_HIBERNATION_REQ_EVENT: + LocalCoreHandle->EventCallbacks.DevHibernationCallback =3D NULL; + break; + + case USB_DEVICE_SOF_EVENT: + LocalCoreHandle->EventCallbacks.DevSofCallback =3D NULL; + break; + + case USB_DEVICE_ERRATIC_ERR_EVENT: + LocalCoreHandle->EventCallbacks.DevErraticErrCallback =3D NULL; + break; + + case USB_DEVICE_CMD_CMPLT_EVENT: + LocalCoreHandle->EventCallbacks.DevCmdCmpltCallback =3D NULL; + break; + + case USB_DEVICE_BUFF_OVERFLOW_EVENT: + LocalCoreHandle->EventCallbacks.DevBuffOvflwCallback =3D NULL; + break; + + case USB_DEVICE_TEST_LMP_RX_EVENT: + LocalCoreHandle->EventCallbacks.DevTestLmpRxCallback =3D NULL; + break; + + case USB_DEVICE_SETUP_PKT_RECEIVED: + LocalCoreHandle->EventCallbacks.DevSetupPktReceivedCallback =3D NULL= ; + break; + + case USB_DEVICE_XFER_NRDY: + LocalCoreHandle->EventCallbacks.DevXferNrdyCallback =3D NULL; + break; + + case USB_DEVICE_XFER_DONE: + LocalCoreHandle->EventCallbacks.DevXferDoneCallback =3D NULL; + break; + + default: + break; + } + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used as an interrupt service routine + @CoreHandle: xDCI controller handle + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreIsrRoutine ( + IN VOID *CoreHandle + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + UINT32 BaseAddr; + UINT32 eventCount; + UINT32 ProcessedEventCount; + UINT32 i; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreIsrRoutine: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + if (LocalCoreHandle->InterrupProcessing =3D=3D TRUE) { + DEBUG ((DEBUG_INFO, "interrupProcessing.........\n")); + return EFI_SUCCESS; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + // + // Event Buffer corresponding to each interrupt line needs + // to be Processed + // + LocalCoreHandle->InterrupProcessing =3D TRUE; + for (i =3D 0; i < LocalCoreHandle->MaxDevIntLines; i++) { + // + // Get the number of events HW has written for this + // interrupt line + // + eventCount =3D UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i)); + eventCount &=3D DWC_XDCI_EVNTCOUNT_MASK; + ProcessedEventCount =3D 0; + + // + // Process interrupt line Buffer only if count is non-zero + // + if (eventCount) { + // + // Process events in this Buffer + // + DwcXdciProcessInterruptLineEvents (LocalCoreHandle, eventCount, &Pro= cessedEventCount); + // + // Write back the Processed number of events so HW decrements it fro= m current + // event count + // + UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), ProcessedEventCou= nt); + } + } + LocalCoreHandle->InterrupProcessing =3D FALSE; + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used as an interrupt service routine and it processes o= nly one event at a time. + @CoreHandle: xDCI controller handle + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreIsrRoutineTimerBased ( + IN VOID *CoreHandle + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + UINT32 BaseAddr; + UINT32 eventCount; + UINT32 ProcessedEventCount; + UINT32 currentEventAddr; + UINT32 ProcessedEventSize =3D 0; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreIsrRoutineTimerBased: INVALID handle\n= ")); + return EFI_DEVICE_ERROR; + } + + if (LocalCoreHandle->CurrentEventBuffer =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreIsrRoutineTimerBased: INVALID e= vent Buffer\n")); + return EFI_INVALID_PARAMETER; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + eventCount =3D UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0)) & DWC_X= DCI_EVNTCOUNT_MASK; + + if (LocalCoreHandle->InterrupProcessing =3D=3D TRUE) { + DEBUG ((DEBUG_INFO, "interrupProcessing.........\n")); + return EFI_SUCCESS; + } + + LocalCoreHandle->InterrupProcessing =3D TRUE; + + ProcessedEventCount =3D 0; + currentEventAddr =3D (UINT32)(UINTN)(LocalCoreHandle->CurrentEventBuffer= ); + + if (LocalCoreHandle->CurrentEventBuffer->Event & DWC_XDCI_EVENT_DEV_MASK= ) { + DwcXdciProcessDeviceEvent ( + LocalCoreHandle, + LocalCoreHandle->CurrentEventBuffer, + &ProcessedEventSize + ); + } else { + DwcXdciProcessEpEvent ( + LocalCoreHandle, + LocalCoreHandle->CurrentEventBuffer, + &ProcessedEventSize); + } + + eventCount -=3D ProcessedEventSize; + ProcessedEventCount +=3D ProcessedEventSize; + if ((currentEventAddr + ProcessedEventSize) >=3D + ((UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers) + (sizeof(DWC= _XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)) + ) { + currentEventAddr =3D (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuff= ers); + DEBUG ((DEBUG_INFO, "DwcXdciProcessInterruptLineEvents: Event Buffer b= ound reached\n")); + } else { + currentEventAddr +=3D ProcessedEventSize; + } + + LocalCoreHandle->CurrentEventBuffer =3D (DWC_XDCI_EVENT_BUFFER *)(UINTN)= currentEventAddr; + UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0), ProcessedEventCount); + LocalCoreHandle->InterrupProcessing =3D FALSE; + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to enable xDCI to connect to the host + @CoreHandle: xDCI controller handle + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreConnect ( + IN VOID *CoreHandle + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + UINT32 MaxDelayIter =3D DWC_XDCI_MAX_DELAY_ITERATIONS; + UINT32 BaseAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreConnect: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + // + // Clear KeepConnect bit so we can allow disconnect and re-connect + // Also issue No action on state change to aVOID any link change + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCTL_REG, + (UsbRegRead(BaseAddr, DWC_XDCI_DCTL_REG) & ~DWC_XDCI_DCTL_KEEP_CONNECT= _MASK) & ~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK + ); + + // + // Set Run bit to connect to the host + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCTL_REG, + UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | DWC_XDCI_DCTL_RUN_STOP_MASK + ); + + // + // Wait until core starts running + // + do { + if (!(UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG) & DWC_XDCI_DSTS_DEV_CTR= L_HALTED_MASK)) { + break; + } else { + gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS); + } + } while (--MaxDelayIter); + + if (!MaxDelayIter) { + DEBUG ((DEBUG_INFO, "Failed to run the device controller\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to disconnect xDCI from the host + @CoreHandle: xDCI controller handle + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreDisconnect ( + IN VOID *CoreHandle + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + UINT32 MaxDelayIter =3D DWC_XDCI_MAX_DELAY_ITERATIONS; + UINT32 BaseAddr; + UINT32 eventCount; + UINT32 dsts; + UINT32 i; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + eventCount =3D UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0)); + eventCount &=3D DWC_XDCI_EVNTCOUNT_MASK; + + DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: eventCount=3D%d\n", eventCou= nt)); + while (eventCount) { + DwcXdciCoreIsrRoutine(LocalCoreHandle); + eventCount =3D UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0)); + eventCount &=3D DWC_XDCI_EVNTCOUNT_MASK; + DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: eventCount=3D%d\n", eventC= ount)); + } + + // + // Issue DEPENDXFER for active transfers + // + for (i =3D 0; i < DWC_XDCI_MAX_ENDPOINTS; i++){ + if (LocalCoreHandle->EpHandles[i].CurrentXferRscIdx){ + DwcXdciEndXfer(LocalCoreHandle, i); + } + } + // + // Clear Run bit to disconnect from host + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCTL_REG, + UsbRegRead(BaseAddr, DWC_XDCI_DCTL_REG) & ~DWC_XDCI_DCTL_RUN_STOP_MASK= ); + + // + // Wait until core is halted + // + do { + dsts =3D UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG); + DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: waiting halt: DSTS=3D0x%x\= n", dsts)); + if ((dsts & DWC_XDCI_DSTS_DEV_CTRL_HALTED_MASK) !=3D 0){ + break; + } else { + gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS); + } + } while (--MaxDelayIter); + + if (!MaxDelayIter) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: Failed to halt the device = controller\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to obtain current USB bus Speed + @CoreHandle: xDCI controller handle + @Speed: Address of variable to save the Speed + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreGetSpeed ( + IN VOID *CoreHandle, + IN USB_SPEED *Speed + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreGetSpeed: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + if (Speed =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreGetSpeed: INVALID parameter\n")); + return EFI_INVALID_PARAMETER; + } + + *Speed =3D UsbRegRead (LocalCoreHandle->BaseAddress, DWC_XDCI_DSTS_REG) = & DWC_XDCI_DSTS_CONN_SPEED_MASK; + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to obtain current USB bus Speed + @CoreHandle: xDCI controller handle + @address: USB address to set (assigned by USB host) + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreSetAddress ( + IN VOID *CoreHandle, + IN UINT32 address + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + UINT32 BaseAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreSetAddress: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + DEBUG ((DEBUG_INFO, "DwcXdciCoreSetAddress is 0x%x \n", address)); + // + // Program USB device address + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCFG_REG, + (UsbRegRead(BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DEV_ADDRESS_= MASK) | (address << DWC_XDCI_DCFG_DEV_ADDRESS_BIT_POS) + ); + + LocalCoreHandle->DevState =3D UsbDevStateAddress; + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", Usb= RegRead (BaseAddr, DWC_XDCI_GCTL_REG))); + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n", U= sbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG))); + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", Usb= RegRead (BaseAddr, DWC_XDCI_DCFG_REG))); + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", Usb= RegRead (BaseAddr, DWC_XDCI_DSTS_REG))); + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to set configuration + @CoreHandle: xDCI controller handle + @ConfigNum: config num to set (assigned by USB host) + +**/ +EFI_STATUS +EFIAPI +DwcXdciCoreSetConfig ( + IN VOID *CoreHandle, + IN UINT32 ConfigNum + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)C= oreHandle; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + EFI_STATUS status; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + // + // Issue DEPSTARTCFG command on EP0 (new config for + // non-control EPs) + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[0].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE, + EPCMD_START_NEW_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: Failed to init params for E= PCMD_START_NEW_CONFIG command\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 0, + (EPCMD_START_NEW_CONFIG | (2 << DWC_XDCI_EPCMD_RES_IDX_BIT_PO= S)), + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: Failed to issue EPCMD_START= _NEW_CONFIG command\n")); + return status; + } + + return status; +} + + +/** + Interface: + This function is used to set link state + @CoreHandle: xDCI controller handle + @state: Desired link state + +**/ +EFI_STATUS +EFIAPI +DwcXdciSetLinkState ( + IN VOID *CoreHandle, + IN USB_DEVICE_SS_LINK_STATE state + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + UINT32 BaseAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciSetLinkState: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + // + // Clear old mask + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCTL_REG, + UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & ~DWC_XDCI_DCTL_STATE_CHANGE= _REQ_MASK + ); + + // + // Request new state + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCTL_REG, + UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | (state << DWC_XDCI_DCTL_STA= TE_CHANGE_REQ_BIT_POS) + ); + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to initialize endpoint + @CoreHandle: xDCI controller handle + @EpInfo: Address of structure describing properties of EP + to be initialized + +**/ +EFI_STATUS +EFIAPI +DwcXdciInitEp ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)C= oreHandle; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + EFI_STATUS status; + UINT32 EpNum; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciInitEp: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + // + // Convert to physical endpoint + // + EpNum =3D DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir); + + // + // Save EP properties + // + CopyMem (&(LocalCoreHandle->EpHandles[EpNum].EpInfo), EpInfo, sizeof (US= B_EP_INFO)); + + // + // Init CheckFlag + // + LocalCoreHandle->EpHandles[EpNum].CheckFlag =3D FALSE; + + // + // Init DEPCFG cmd params for EP + // + status =3D DwcXdciCoreInitEpCmdParams ( + CoreHandle, + &LocalCoreHandle->EpHandles[EpNum].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to init params for EPCMD_S= ET_EP_CONFIG command\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + CoreHandle, + EpNum, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to issue EPCMD_SET_EP_CONF= IG command\n")); + return status; + } + + // + // Issue a DEPXFERCFG command for endpoint + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[EpNum].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to init params for EPCMD_S= ET_EP_XFER_RES_CONFIG command\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + EpNum, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to issue EPCMD_SET_EP_XFER_= RES_CONFIG command\n")); + } + + return status; +} + + +/** + Interface: + This function is used to enable non-Ep0 endpoint + @CoreHandle: xDCI controller handle + @EpInfo: Address of structure describing properties of EP + to be enabled + +**/ +EFI_STATUS +EFIAPI +DwcXdciEpEnable ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + UINT32 EpNum; + UINT32 BaseAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpEnable: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + // + // Convert to physical endpoint + // + EpNum =3D DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir); + + // + // Enable Physical Endpoint EpNum + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EP_DALEPENA_REG, + UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << EpNum) + ); + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to disable non-Ep0 endpoint + @CoreHandle: xDCI controller handle + @EpInfo: Address of structure describing properties of EP + to be enabled + +**/ +EFI_STATUS +EFIAPI +DwcXdciEpDisable ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + UINT32 EpNum; + UINT32 BaseAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpDisable: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + // + // Convert to physical endpoint + // + EpNum =3D DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir); + + // + // Disable Physical Endpoint EpNum + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EP_DALEPENA_REG, + UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) & ~(1 << EpNum) + ); + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to STALL and endpoint + @CoreHandle: xDCI controller handle + @EpInfo: Address of structure describing properties of EP + to be enabled + +**/ +EFI_STATUS +EFIAPI +DwcXdciEpStall ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)C= oreHandle; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + EFI_STATUS status; + UINT32 EpNum; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpStall: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + // + // Convert to physical endpoint + // + EpNum =3D DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir); + + // + // Set Ep State Info + // + if (LocalCoreHandle->EpHandles[EpNum].State !=3D USB_EP_STATE_STALLED) { + LocalCoreHandle->EpHandles[EpNum].OrgState =3D LocalCoreHandle->EpHand= les[EpNum].State; + LocalCoreHandle->EpHandles[EpNum].State =3D USB_EP_STATE_STALLED; + } + // + // Issue a DWC_XDCI_EPCMD_SET_STALL for EP + // Reset params + // + EpCmdParams.Param0 =3D EpCmdParams.Param1 =3D EpCmdParams.Param2 =3D 0; + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + EpNum, + DWC_XDCI_EPCMD_SET_STALL, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciEpStall: Failed to issue EP stall command\n= ")); + } + + return status; +} + + +/** + Interface: + This function is used to clear endpoint STALL + @CoreHandle: xDCI controller handle + @EpInfo: Address of structure describing properties of EP + to be enabled + +**/ +EFI_STATUS +EFIAPI +DwcXdciEpClearStall ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)C= oreHandle; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + EFI_STATUS status; + UINT32 EpNum; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpClearStall: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + // + // Convert to physical endpoint + // + EpNum =3D DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir); + + // + // Set Ep State Info + // + LocalCoreHandle->EpHandles[EpNum].State =3D LocalCoreHandle->EpHandles[E= pNum].OrgState; + + // + // Issue a DWC_XDCI_EPCMD_CLEAR_STALL for EP + // Reset params + // + EpCmdParams.Param0 =3D EpCmdParams.Param1 =3D EpCmdParams.Param2 =3D 0; + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + EpNum, + DWC_XDCI_EPCMD_CLEAR_STALL, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciEpStall: Failed to issue EP clea stall comm= and\n")); + } + + return status; +} + + +/** + Interface: + This function is used to set endpoint in NOT READY state + @CoreHandle: xDCI controller handle + @EpInfo: Address of structure describing properties of EP + to be enabled + +**/ +EFI_STATUS +EFIAPI +DwcXdciEpSetNrdy ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)CoreHandle; + UINT32 EpNum; + UINT32 BaseAddr; + UINT32 MaxDelayIter =3D DWC_XDCI_MAX_DELAY_ITERATIONS; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpSetNrdy: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + // + // Convert to physical endpoint + // + EpNum =3D DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir); + + // + // Program the EP number in command's param reg + // + UsbRegWrite (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG, EpNum); + + // + // Issue EP not ready generic device command + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DGCMD_REG, + (UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SET_EP= _NRDY) + ); + + // + // Activate the command + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DGCMD_REG, + (UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_ACTIVE= _MASK) + ); + + // + // Wait until command completes + // + do { + if (!(UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_A= CTIVE_MASK)) + break; + else + gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS); + } while (--MaxDelayIter); + + if (!MaxDelayIter) { + DEBUG ((DEBUG_INFO, "Failed to issue Command\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Interface: + This function is used to queue receive SETUP packet request + @CoreHandle: xDCI controller handle + @Buffer: Address of Buffer to receive SETUP packet + +**/ +EFI_STATUS +EFIAPI +DwcXdciEp0ReceiveSetupPkt ( + IN VOID *CoreHandle, + IN UINT8 *Buffer + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *= )CoreHandle; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + DWC_XDCI_TRB *Trb; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveSetupPkt: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + LocalCoreHandle->EpHandles[0].EpInfo.EpNum =3D 0; + LocalCoreHandle->EpHandles[0].EpInfo.EpDir =3D 0; + LocalCoreHandle->EpHandles[0].State =3D USB_EP_STATE_SETUP; + Trb =3D LocalCoreHandle->Trbs; + DEBUG ((DEBUG_INFO, "(DwcXdciEp0ReceiveSetupPkt)\n")); + + Status =3D DwcXdciCoreInitTrb ( + LocalCoreHandle, + Trb, + TRBCTL_SETUP, + Buffer, + 8 + ); + + if (Status) { + DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveSetupPkt: Init TRB Failed \n")); + return Status; + } + + // + // Issue a DEPSTRTXFER for EP0 + // Reset params + // + EpCmdParams.Param0 =3D EpCmdParams.Param1 =3D EpCmdParams.Param2 =3D 0; + + // + // Init the lower re-bits for TRB address + // + EpCmdParams.Param1 =3D (UINT32)(UINTN)Trb; + + // + // Issue the command + // + Status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 0, + EPCMD_START_XFER, + &EpCmdParams + ); + + if (Status) { + DEBUG ((DEBUG_INFO, "\nDwcXdciEp0ReceiveSetupPkt: Failed to issue Star= t Transfer command")); + } + + // + // Save new resource index for this transfer + // + LocalCoreHandle->EpHandles[0].CurrentXferRscIdx =3D ((UsbRegRead(LocalCo= reHandle->BaseAddress, DWC_XDCI_EPCMD_REG(0)) & + DWC_XDCI_EPCMD_RE= S_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS + ); + + return Status; +} + + +/** + Interface: + This function is used to queue receive status packet on EP0 + @CoreHandle: xDCI controller handle + +**/ +EFI_STATUS +EFIAPI +DwcXdciEp0ReceiveStatusPkt ( + IN VOID *CoreHandle + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *= )CoreHandle; + DWC_XDCI_TRB *Trb; + DWC_XDCI_TRB_CONTROL TrbCtrl; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + EFI_STATUS Status; + UINT32 BaseAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveStatusPkt: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + // + // We are receiving on EP0 so physical EP is 0 + // + Trb =3D LocalCoreHandle->Trbs; + DEBUG ((DEBUG_INFO, "(DwcXdciEp0ReceiveStatusPkt)\n")); + if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) { + DEBUG ((DEBUG_INFO, "statusPkt still not transferred.\n")); + return EFI_SUCCESS; + } + + LocalCoreHandle->EpHandles[0].EpInfo.EpNum =3D 0; + LocalCoreHandle->EpHandles[0].EpInfo.EpDir =3D 0; + + // + // OUT data phase for 3-phased control transfer + // + TrbCtrl =3D TRBCTL_3_PHASE; + + // + // Init TRB for the transfer + // + Status =3D DwcXdciCoreInitTrb ( + LocalCoreHandle, + Trb, + TrbCtrl, + LocalCoreHandle->AlignedSetupBuffer, + 0 + ); + + if (!Status) { + // + // Issue a DEPSTRTXFER for EP0 + // Reset params + // + EpCmdParams.Param0 =3D EpCmdParams.Param1 =3D EpCmdParams.Param2 =3D 0= ; + + // + // Init the lower bits for TRB address + // + EpCmdParams.Param1 =3D (UINT32)(UINTN)Trb; + + // + // Issue the command + // + Status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 0, + EPCMD_START_XFER, + &EpCmdParams + ); + + if (Status) { + DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveStatusPkt: Failed to issue Sta= rt Transfer command for EP0\n")); + } + // + // Save new resource index for this transfer + // + LocalCoreHandle->EpHandles[0].CurrentXferRscIdx =3D ((UsbRegRead(BaseA= ddr, DWC_XDCI_EPCMD_REG(0)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCM= D_RES_IDX_BIT_POS); + + // + // TODO: We are not using the EP state for control transfers + // right now simply because we're only supporting IN + // data phase. For the current use case, we don't + // need OUT data phase. We can add that later and we will + // add some of the state and SETUP packet awareness code + // + LocalCoreHandle->EpHandles[0].State =3D USB_EP_STATE_STATUS; + } + + return Status; +} + + +/** + Interface: + This function is used to send status packet on EP0 + @CoreHandle: xDCI controller handle + +**/ +EFI_STATUS +EFIAPI +DwcXdciEp0SendStatusPkt ( + IN VOID *CoreHandle + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *= )CoreHandle; + DWC_XDCI_TRB *Trb; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + EFI_STATUS Status; + UINT32 BaseAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + // + // We are sending on EP0 so physical EP is 1 + // + Trb =3D (LocalCoreHandle->Trbs + (1 * DWC_XDCI_TRB_NUM)); + DEBUG ((DEBUG_INFO, "(DwcXdciEp0SendStatusPkt)\n")); + + LocalCoreHandle->EpHandles[0].State =3D USB_EP_STATE_STATUS; + Status =3D DwcXdciCoreInitTrb ( + LocalCoreHandle, + Trb, + TRBCTL_2_PHASE, + LocalCoreHandle->AlignedMiscBuffer, + 0 + ); + + if (Status) { + DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: TRB failed during status= phase\n")); + return Status; + } + + // + // Issue a DEPSTRTXFER for EP1 + // Reset params + // + EpCmdParams.Param0 =3D EpCmdParams.Param1 =3D EpCmdParams.Param2 =3D 0; + + // + // Init the lower re-bits for TRB address + // + EpCmdParams.Param1 =3D (UINT32)(UINTN)Trb; + + // + // Issue the command + // + Status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 1, + EPCMD_START_XFER, + &EpCmdParams + ); + + if (Status) { + DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: Failed to issue Start Tr= ansfer on EP0\n")); + } + + // + // Save new resource index for this transfer + // + LocalCoreHandle->EpHandles[1].CurrentXferRscIdx =3D ((UsbRegRead(BaseAdd= r, DWC_XDCI_EPCMD_REG(1)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_= RES_IDX_BIT_POS); + LocalCoreHandle->EpHandles[0].State =3D USB_EP_STATE_STATUS; + + return Status; +} + + +/** + Interface: + This function is used to send data on non-EP0 endpoint + @CoreHandle: xDCI controller handle + @EpInfo: Address of structure describing properties of EP + @Buffer: Buffer containing data to transmit + @size: Size of transfer (in bytes) + +**/ +EFI_STATUS +EFIAPI +DwcXdciEpTxData ( + IN VOID *CoreHandle, + IN USB_XFER_REQUEST *XferReq + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)C= oreHandle; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + DWC_XDCI_TRB *Trb; + DWC_XDCI_TRB_CONTROL TrbCtrl; + EFI_STATUS Status; + UINT32 EpNum; + UINT32 BaseAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + if (XferReq =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: INVALID transfer request\n")); + return EFI_INVALID_PARAMETER; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + // + // Convert to physical endpoint + // + EpNum =3D DwcXdciGetPhysicalEpNum ( + XferReq->EpInfo.EpNum, + XferReq->EpInfo.EpDir + ); + + Trb =3D (LocalCoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM)); + DEBUG ((DEBUG_INFO, "(DwcXdciEpTxData)EpNum is %d\n", EpNum)); + + + if (EpNum > 1) + TrbCtrl =3D TRBCTL_NORMAL; + else + TrbCtrl =3D TRBCTL_CTRL_DATA_PHASE; + + if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) { + Status =3D DwcXdciEndXfer (LocalCoreHandle, EpNum); + if (Status) { + DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: Failed to end previous transfe= r\n")); + } + + Status =3D DwcXdciCoreFlushEpTxFifo (LocalCoreHandle, EpNum); + if (Status) { + DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: Failed to end previous transfe= r\n")); + } + } + + // + // Data phase + // + CopyMem (&(LocalCoreHandle->EpHandles[EpNum].XferHandle), XferReq, sizeo= f (USB_XFER_REQUEST)); + LocalCoreHandle->EpHandles[EpNum].State =3D USB_EP_STATE_DATA; + + LocalCoreHandle->EpHandles[EpNum].Trb =3D Trb; + + Status =3D DwcXdciCoreInitTrb ( + LocalCoreHandle, + Trb, + TrbCtrl, + XferReq->XferBuffer, + XferReq->XferLen + ); + + if (Status) { + DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: TRB failed\n")); + return Status; + } + + // + // Issue a DEPSTRTXFER for EP + // Reset params + // + EpCmdParams.Param0 =3D EpCmdParams.Param1 =3D EpCmdParams.Param2 =3D 0; + + // + // Init the lower re-bits for TRB address + // + EpCmdParams.Param1 =3D (UINT32)(UINTN)Trb; + + // + // Issue the command + // + Status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + EpNum, + EPCMD_START_XFER, + &EpCmdParams + ); + + // + // Save new resource index for this transfer + // + LocalCoreHandle->EpHandles[EpNum].CurrentXferRscIdx =3D ((UsbRegRead (Ba= seAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XD= CI_EPCMD_RES_IDX_BIT_POS); + + return Status; +} + + +/** + Interface: + This function is used to receive data on non-EP0 endpoint + @CoreHandle: xDCI controller handle + @EpInfo: Address of structure describing properties of EP + @Buffer: Buffer containing data to transmit + @size: Size of transfer (in bytes) + +**/ +EFI_STATUS +EFIAPI +DwcXdciEpRxData ( + IN VOID *CoreHandle, + IN USB_XFER_REQUEST *XferReq + ) +{ + XDCI_CORE_HANDLE *LocalCoreHandle =3D (XDCI_CORE_HANDLE *)C= oreHandle; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + DWC_XDCI_TRB *Trb; + DWC_XDCI_TRB_CONTROL TrbCtrl; + EFI_STATUS Status; + UINT32 EpNum; + UINT32 BaseAddr; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + if (XferReq =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: INVALID transfer request\n")); + return EFI_INVALID_PARAMETER; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + // + // Convert to physical endpoint + // + EpNum =3D DwcXdciGetPhysicalEpNum (XferReq->EpInfo.EpNum, XferReq->EpInf= o.EpDir); + + Trb =3D (LocalCoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM)); + DEBUG ((DEBUG_INFO, "(DwcXdciEpRxData)EpNum is %d\n", EpNum)); + + if (EpNum > 1) + TrbCtrl =3D TRBCTL_NORMAL; + else + TrbCtrl =3D TRBCTL_CTRL_DATA_PHASE; + + // + // If CheckFlag didn't set to FALSE, means the previous transfer request= didn't complete, + // need to wait the previous request done. + // + if (LocalCoreHandle->EpHandles[EpNum].CheckFlag =3D=3D TRUE) { + return EFI_NOT_READY; + } + + LocalCoreHandle->EpHandles[EpNum].CheckFlag =3D TRUE; + + // + // Data phase + // + CopyMem (&(LocalCoreHandle->EpHandles[EpNum].XferHandle), XferReq, sizeo= f (USB_XFER_REQUEST)); + + LocalCoreHandle->EpHandles[EpNum].State =3D USB_EP_STATE_DATA; + + LocalCoreHandle->EpHandles[EpNum].Trb =3D Trb; + + DEBUG ((DEBUG_INFO, "(DwcXdciEpRxData)XferReq->XferLen is 0x%x\n", XferR= eq->XferLen)); + + Status =3D DwcXdciCoreInitTrb ( + LocalCoreHandle, + Trb, + TrbCtrl, + XferReq->XferBuffer, + XferReq->XferLen + ); + + if (Status) { + DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: TRB failed\n")); + return Status; + } + // + // Issue a DEPSTRTXFER for EP + // Reset params + // + EpCmdParams.Param0 =3D EpCmdParams.Param1 =3D EpCmdParams.Param2 =3D 0; + + // + // Init the lower re-bits for TRB address + // + EpCmdParams.Param1 =3D (UINT32)(UINTN)Trb; + + // + // Issue the command + // + Status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + EpNum, + EPCMD_START_XFER, + &EpCmdParams + ); + + if (Status) { + DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: Failed to start transfer\n")); + } + + // + // Save new resource index for this transfer + // + LocalCoreHandle->EpHandles[EpNum].CurrentXferRscIdx =3D ((UsbRegRead(Bas= eAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDC= I_EPCMD_RES_IDX_BIT_POS); + + return Status; +} + + + +STATIC +EFI_STATUS +DwcXdciCoreFlushEpFifo ( + IN XDCI_CORE_HANDLE *CoreHandle, + IN UINT32 EpNum + ) +{ + UINT32 BaseAddr; + UINT32 MaxDelayIter =3D DWC_XDCI_MAX_DELAY_ITERATIONS; + UINT32 fifoNum; + UINT32 Param; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushEpTxFifo: INVALID handle\n= ")); + return EFI_DEVICE_ERROR; + } + + BaseAddr =3D CoreHandle->BaseAddress; + + // + // Translate to FIFOnum + // NOTE: Assuming this is a Tx EP + // + fifoNum =3D (EpNum >> 1); + + // + // TODO: Currently we are only using TxFIFO 0. Later map these + // Write the FIFO num/dir param for the generic command. + // + + Param =3D UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG); + Param &=3D ~(DWC_XDCI_DGCMD_PARAM_TX_FIFO_NUM_MASK | DWC_XDCI_DGCMD_PARA= M_TX_FIFO_DIR_MASK); + + if ((EpNum & 0x01) !=3D 0) { + Param |=3D (fifoNum | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK); + } else { + Param |=3D fifoNum; + } + + DEBUG ((DEBUG_INFO, "USB FU Flash: CMD 0x%08x :: Param 0x%08x\n", + (UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SEL= _FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK), + Param)); + + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DGCMD_PARAM_REG, + Param + ); + + // + // Write the command to flush all FIFOs + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DGCMD_REG, + (UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) | DWC_XDCI_DGCMD_CMD_SEL_FIF= O_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK) + ); + + + // + // Wait until command completes + // + do { + if (!(UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_AC= TIVE_MASK)) + break; + else + gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS); + } while (--MaxDelayIter); + + if (!MaxDelayIter) { + DEBUG ((DEBUG_INFO, "Failed to issue Command\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Interface: + This function is used to cancel a transfer on non-EP0 endpoint + @CoreHandle: xDCI controller handle + @EpInfo: Address of structure describing properties of EP + +**/ +EFI_STATUS +EFIAPI +DwcXdciEpCancelTransfer ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + UINT32 EpNum; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpCancelTransfer: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + // + // Get physical EP num + // + EpNum =3D DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir); + Status =3D DwcXdciEndXfer(CoreHandle, EpNum); + DwcXdciCoreFlushEpFifo(CoreHandle, EpNum); + + return Status; +} + + +EFI_STATUS +usbProcessDeviceResetDet ( + IN XDCI_CORE_HANDLE *CoreHandle + ) +{ + return DwcXdciProcessDeviceResetDet (CoreHandle); +} + +EFI_STATUS +usbProcessDeviceResetDone ( + IN XDCI_CORE_HANDLE *CoreHandle + ) +{ + return DwcXdciProcessDeviceResetDone (CoreHandle); +} + +UINT32 +UsbGetPhysicalEpNum ( + IN UINT32 EndpointNum, + IN USB_EP_DIR EndpointDir + ) +{ + return DwcXdciGetPhysicalEpNum( + EndpointNum, + EndpointDir + ); +} + + +EFI_STATUS +EFIAPI +UsbXdciCoreReinit ( + IN VOID *CoreHandle + ) +{ + EFI_STATUS status =3D EFI_DEVICE_ERROR; + UINT32 BaseAddr; + XDCI_CORE_HANDLE *LocalCoreHandle; + DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams; + UINT32 MaxDelayIter =3D DWC_XDCI_MAX_DELAY_ITER= ATIONS; + UINT8 i; + + LocalCoreHandle =3D CoreHandle; + + if (CoreHandle =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (LocalCoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to allocate handle for xD= CI\n")); + return EFI_OUT_OF_RESOURCES; + } + + BaseAddr =3D LocalCoreHandle->BaseAddress; + + DEBUG ((DEBUG_INFO, "Resetting the USB core\n")); + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCTL_REG, + UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) | DWC_XDCI_DCTL_CSFTRST_MASK + ); + + // + // Wait until core soft reset completes + // + do { + if (!(UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & DWC_XDCI_DCTL_CSFTRST= _MASK)) { + break; + } else { + gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS); + } + } while (--MaxDelayIter); + + if (!MaxDelayIter) { + DEBUG ((DEBUG_INFO, "Failed to reset device controller\n")); + return EFI_DEVICE_ERROR; + } + + DEBUG ((DEBUG_INFO, "USB core has been reset\n")); + + LocalCoreHandle->DevState =3D UsbDevStateDefault; + + // + // Clear KeepConnect bit so we can allow disconnect and + // re-connect. Stay in RX_DETECT state + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCTL_REG, + UsbRegRead (BaseAddr, DWC_XDCI_DCTL_REG) & + (~DWC_XDCI_DCTL_KEEP_CONNECT_MASK) & + (~DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK) | + (DWC_XDCI_DCTL_STATE_CHANGE_REQ_RX_DETECT << DWC_XDCI_DCTL_STATE_CHANG= E_REQ_BIT_POS) + ); + + DEBUG ((DEBUG_INFO, "Device controller Synopsys ID: %x\n", UsbRegRead (B= aseAddr, DWC_XDCI_GSNPSID_REG))); + DEBUG ((DEBUG_INFO, "Default value of xDCI GSBUSCFG0 and GSBUSCFG1: %x, = %x\n", + UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG0_REG), + UsbRegRead (BaseAddr, DWC_XDCI_GSBUSCFG1_REG))); + + DEBUG ((DEBUG_INFO, "Default value of xDCI GTXTHRCFG and GRXTHRCFG: %x, = %x\n", + UsbRegRead (BaseAddr, DWC_XDCI_GTXTHRCFG_REG), + UsbRegRead (BaseAddr, DWC_XDCI_GRXTHRCFG_REG))); + + // + // Clear ULPI auto-resume bit + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB2PHYCFG_REG (0), + (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)) & ~DWC_XDCI_GUSB2= PHYCFG_ULPI_AUTO_RESUME_MASK) + ); + + DEBUG ((DEBUG_INFO, "Default value of xDCI GUSB2PHYCFG and GUSB3PIPECTL:= %x, %x\n", + UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG (0)), + UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG (0)))); + + // + // Only one RxFIFO + // + DEBUG ((DEBUG_INFO, "Default value of DWC_XDCI_GRXFIFOSIZ: %x\n", + UsbRegRead (BaseAddr, DWC_XDCI_GRXFIFOSIZ_REG (0)))); + + for (i =3D 0; i < DWC_XDCI_MAX_ENDPOINTS; i++) { + DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_GTXFIFOSIZ %d: %x\= n", + i, UsbRegRead (BaseAddr, DWC_XDCI_GTXFIFOSIZ_REG (i)))); + } + + // + // TODO: Need to check if TxFIFO should start where RxFIFO ends + // or default is correct i.e. TxFIFO starts at 0 just like RxFIFO + // + + // + // Allocate and Initialize Event Buffers + // + LocalCoreHandle->MaxDevIntLines =3D ((UsbRegRead (BaseAddr, DWC_XDCI_GHW= PARAMS1_REG) & + DWC_XDCI_GHWPARAMS1_NUM_INT_MAS= K) >> + DWC_XDCI_GHWPARAMS1_NUM_INT_BIT= _POS); + + DEBUG ((DEBUG_INFO, "Max dev int lines: %d\n", LocalCoreHandle->MaxDevIn= tLines)); + // + // One event Buffer per interrupt line. + // Need to align it to size of event Buffer + // Buffer needs to be big enough. Otherwise the core + // won't operate + // + LocalCoreHandle->AlignedEventBuffers =3D (DWC_XDCI_EVENT_BUFFER *) + ((UINT32)(UINTN)(LocalCoreHan= dle->EventBuffers) + + ((sizeof (DWC_XDCI_EVENT_BUFF= ER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) - + (((UINT32)(UINTN)(LocalCoreHa= ndle->EventBuffers)) % + (sizeof (DWC_XDCI_EVENT_BUFFE= R) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)))); + + for (i =3D 0; i < LocalCoreHandle->MaxDevIntLines; i++) { + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GEVNTADR_REG (i), + (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers + i * sizeof(DW= C_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) + ); + + // + // Clear High 32bit address register, GEVNTADR register is 64-bit regi= ster + // default is 0xffffffffffffffff + // + UsbRegWrite (BaseAddr, DWC_XDCI_GEVNTADR_REG (i) + 4, 0x00000000); + + LocalCoreHandle->CurrentEventBuffer =3D LocalCoreHandle->AlignedEventB= uffers; + // + // Write size and clear the mask + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EVNTSIZ_REG (i), + sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER + ); + + // + // Write 0 to the event count register as the last step + // for event configuration + // + UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), 0); + + DEBUG ((DEBUG_INFO, "Value of xDCI Event Buffer %d: %x, Size: %x, Coun= t: %x\n", + i, + UsbRegRead (BaseAddr, DWC_XDCI_GEVNTADR_REG (i)), + UsbRegRead (BaseAddr, DWC_XDCI_EVNTSIZ_REG (i)), + UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i)))= ); + } + + // + // Program Global Control Register to disable scaledown, + // disable clock gating + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GCTL_REG, + ((UsbRegRead(BaseAddr, DWC_XDCI_GCTL_REG) & + ~(DWC_XDCI_GCTL_SCALE_DOWN_MODE_MASK + DWC_XDCI_GCTL_R= AMCLKSEL_MASK + DWC_XDCI_GCTL_DISABLE_SCRAMB_MASK)) | + DWC_XDCI_GCTL_DISABLE_CLK_GATING_MASK | + (DWC_XDCI_GCTL_PRT_CAP_DEVICE << DWC_XDCI_GCTL_PRT_CAP= _DIR_BIT_POS))); + + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", U= sbRegRead (BaseAddr, DWC_XDCI_GCTL_REG))); + + + // + // TODO: Program desired Speed and set LPM capable + // We will do this when SuperSpeed works. For now, + // force into High-Speed mode to aVOID anyone trying this + // on Super Speed port + // +#ifdef SUPPORT_SUPER_SPEED + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCFG_REG, + (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV= _SPEED_MASK) | LocalCoreHandle->DesiredSpeed + ); +#else + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DCFG_REG, + (UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG) & ~DWC_XDCI_DCFG_DESIRED_DEV= _SPEED_MASK) | DWC_XDCI_DCFG_DESIRED_HS_SPEED + ); +#endif + + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", Usb= RegRead (BaseAddr, DWC_XDCI_DCFG_REG))); + DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", Usb= RegRead (BaseAddr, DWC_XDCI_DSTS_REG))); + + // + // Enable Device Interrupt Events + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_DEVTEN_REG, + DWC_XDCI_DEVTEN_DEVICE_INTS + ); + + // + // Program the desired role + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GCTL_REG, + (UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG) & ~DWC_XDCI_GCTL_PRT_CAP_DIR= _MASK) | (LocalCoreHandle->Role << DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS) + ); + + // + // Clear USB2 suspend for start new config command + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB2PHYCFG_REG (0), + (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) & ~DWC_XDCI_GUSB2P= HYCFG_SUSPEND_PHY_MASK) + ); + // + // Clear USB3 suspend for start new config command + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_GUSB3PIPECTL_REG (0), + (UsbRegRead (BaseAddr, DWC_XDCI_GUSB3PIPECTL_REG(0)) & ~DWC_XDCI_GUSB3= PIPECTL_SUSPEND_PHY_MASK) + ); + // + // Issue DEPSTARTCFG command for EP0 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[0].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE, + EPCMD_START_NEW_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for START_= NEW_CONFIG EP command on xDCI\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 0, + EPCMD_START_NEW_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue START_NEW_CONFIG= EP command on xDCI\n")); + return status; + } + + // + // Issue DEPCFG command for EP0 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[0].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for SET_EP= _CONFIG command on xDCI for EP0\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 0, + EPCMD_SET_EP_CONFIG, + &EpCmdParams); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG co= mmand on xDCI for EP0\n")); + return status; + } + + // + // Issue DEPCFG command for EP1 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[1].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for SET_EP= _CONFIG command on xDCI for EP1\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 1, + EPCMD_SET_EP_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG co= mmand on xDCI for EP1\n")); + return status; + } + + // + // Issue DEPXFERCFG command for EP0 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[0].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for EPCMD_= SET_EP_XFER_RES_CONFIG command on xDCI for EP0\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 0, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFE= R_RES_CONFIG command on xDCI for EP0\n")); + return status; + } + + // + // Issue DEPXFERCFG command for EP1 + // + status =3D DwcXdciCoreInitEpCmdParams ( + LocalCoreHandle, + &LocalCoreHandle->EpHandles[1].EpInfo, + DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to init params for EPCMD_= SET_EP_XFER_RES_CONFIG command on xDCI for EP1\n")); + return status; + } + + // + // Issue the command + // + status =3D DwcXdciCoreIssueEpCmd ( + LocalCoreHandle, + 1, + EPCMD_SET_EP_XFER_RES_CONFIG, + &EpCmdParams + ); + + if (status) { + DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFE= R_RES_CONFIG command on xDCI for EP1\n")); + return status; + } + + // + // Prepare a Buffer for SETUP packet + // + LocalCoreHandle->Trbs =3D (DWC_XDCI_TRB *)(UINTN)((UINT32)(UINTN) + LocalCoreHandle->UnalignedTrbs + + (DWC_XDCI_TRB_BYTE_ALIGNMENT - + ((UINT32)(UINTN)LocalCoreHandle->UnalignedTrbs= % + DWC_XDCI_TRB_BYTE_ALIGNMENT))); + + DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ unalignedTrbs address is= 0x%x\n", LocalCoreHandle->UnalignedTrbs)); + DEBUG ((DEBUG_INFO, "(DwcXdciCoreInit)@@@@@@@@@ TRB address is 0x%x\n", = LocalCoreHandle->Trbs)); + + // + // Allocate Setup Buffer that is 8-byte aligned + // + LocalCoreHandle->AlignedSetupBuffer =3D LocalCoreHandle->DefaultSetupBuf= fer + + (DWC_XDCI_SETUP_BUFF_SIZE - + ((UINT32)(UINTN)(LocalCoreHand= le->DefaultSetupBuffer) % DWC_XDCI_SETUP_BUFF_SIZE)); + + // + // Aligned Buffer for status phase + // + LocalCoreHandle->AlignedMiscBuffer =3D LocalCoreHandle->MiscBuffer + + (DWC_XDCI_SETUP_BUFF_SIZE - + ((UINT32)(UINTN)(LocalCoreHandl= e->AlignedMiscBuffer) % DWC_XDCI_SETUP_BUFF_SIZE)); + + // + // We will queue SETUP request when we see bus reset + // + + // + // Enable Physical Endpoints 0 + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EP_DALEPENA_REG, + UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 0) + ); + + // + // Enable Physical Endpoints 1 + // + UsbRegWrite ( + BaseAddr, + DWC_XDCI_EP_DALEPENA_REG, + UsbRegRead (BaseAddr, DWC_XDCI_EP_DALEPENA_REG) | (1 << 1) + ); + + DEBUG ((DEBUG_INFO, "Default value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n",= UsbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG))); + return status; + + +} + + +EFI_STATUS +UsbXdciCoreFlushEpFifo ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + UINT32 EpNum; + + if (CoreHandle =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "DwcXdciEpCancelTransfer: INVALID handle\n")); + return EFI_DEVICE_ERROR; + } + + // + // Get physical EP num + // + EpNum =3D DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir); + DwcXdciCoreFlushEpFifo(CoreHandle, EpNum); + + return Status; +} +#pragma optimize ("", on) + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciD= WC.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.h new file mode 100644 index 0000000..3470cfd --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.h @@ -0,0 +1,741 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef _XDCI_DWC_H_ +#define _XDCI_DWC_H_ + +#include "XdciCommon.h" +#include "XdciDevice.h" + +#define DWC_XDCI_MAX_ENDPOINTS (16) +#define DWC_XDCI_SS_CTRL_EP_MPS (512) +#define DWC_XDCI_HS_CTRL_EP_MPS (64) +#define DWC_XDCI_FS_CTRL_EP_MPS (64) +#define DWC_XDCI_LS_CTRL_EP_MPS (8) +#define DWC_XDCI_SS_CTRL_BUF_SIZE (512) +#define DWC_XDCI_SETUP_BUFF_SIZE (8) +#define DWC_XDCI_MAX_EVENTS_PER_BUFFER (16) +#define DWC_XDCI_TRB_BYTE_ALIGNMENT (16) +#define DWC_XDCI_DEFAULT_TX_FIFO_SIZE (1024) +#define DWC_XDCI_TRB_NUM (32) +#define DWC_XDCI_MASK (DWC_XDCI_TRB_N= UM - 1) + +#define DWC_XDCI_MAX_DELAY_ITERATIONS (1000) + +#define DWC_XDCI_GSBUSCFG0_REG (0xC100) +#define DWC_XDCI_GSBUSCFG1_REG (0xC104) +#define DWC_XDCI_GTXTHRCFG_REG (0xC108) +#define DWC_XDCI_GRXTHRCFG_REG (0xC10C) + +// +// Global Control Register and bit definitions +// +#define DWC_XDCI_GCTL_REG (0xC110) +#define DWC_XDCI_GCTL_PWRDNSCALE_MASK (0xFFF80000) +#define DWC_XDCI_GCTL_PWRDNSCALE_VAL (0x13880000) +#define DWC_XDCI_GCTL_U2RSTECN_MASK (0x00010000) +#define DWC_XDCI_GCTL_PRT_CAP_DIR_MASK (0x00003000) +#define DWC_XDCI_GCTL_PRT_CAP_DIR_BIT_POS (12) +#define DWC_XDCI_GCTL_PRT_CAP_HOST (1) +#define DWC_XDCI_GCTL_PRT_CAP_DEVICE (2) +#define DWC_XDCI_GCTL_PRT_CAP_OTG (3) +#define DWC_XDCI_GCTL_RAMCLKSEL_MASK (0x000000C0) +#define DWC_XDCI_GCTL_SCALE_DOWN_MODE_MASK (0x00000030) +#define DWC_XDCI_GCTL_DISABLE_CLK_GATING_MASK (0x00000001) +#define DWC_XDCI_GCTL_DISABLE_SCRAMB_MASK (0x00000008) + +#define DWC_XDCI_GSTS_REG (0xC118) +#define DWC_XDCI_GSNPSID_REG (0xC120) +#define DWC_XDCI_GGPIO_REG (0xC124) +#define DWC_XDCI_GUID_REG (0xC128) +#define DWC_XDCI_GUCTL_REG (0xC12C) +#define DWC_XDCI_GBUSERRADDR (0xC130) + +// +// Global Hardware Parameters Registers +// +#define DWC_XDCI_GHWPARAMS0_REG (0xC140) +#define DWC_XDCI_GHWPARAMS1_REG (0xC144) +#define DWC_XDCI_GHWPARAMS1_NUM_INT_MASK (0x1F8000) +#define DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS (15) + +#define DWC_XDCI_GHWPARAMS2_REG (0xC148) +#define DWC_XDCI_GHWPARAMS3_REG (0xC14C) +#define DWC_XDCI_GHWPARAMS4_REG (0xC150) +#define DWC_XDCI_GHWPARAMS4_CACHE_TRBS_PER_XFER_MASK (0x0000003F) +#define DWC_XDCI_GHWPARAMS5_REG (0xC154) +#define DWC_XDCI_GHWPARAMS6_REG (0xC158) +#define DWC_XDCI_GHWPARAMS7_REG (0xC15C) +#define DWC_XDCI_GHWPARAMS8_REG (0xC600) + +#define DWC_XDCI_GDBGFIFOSPACE_REG (0xC160) + +#define DWC_XDCI_GUSB2PHYCFG_REG(n) (0xC200 + (n <<= 2)) +#define DWC_XDCI_GUSB2PHYCFG_ULPI_AUTO_RESUME_MASK (0x00008000) +#define DWC_XDCI_GUSB2PHYCFG_SUSPEND_PHY_MASK (0x00000040) + +#define DWC_XDCI_GUSB3PIPECTL_REG(n) (0xC2C0 + (n <<= 2)) +#define DWC_XDCI_GUSB3PIPECTL_SUSPEND_PHY_MASK (0x00020000) + +#define DWC_XDCI_GTXFIFOSIZ_REG(n) (0xC300 + (n <<= 2)) +#define DWC_XDCI_GTXFIFOSIZ_START_ADDRESS_MASK (0xFFFF0000) +#define DWC_XDCI_GTXFIFOSIZ_START_ADDRESS_BIT_POS (16) +#define DWC_XDCI_GRXFIFOSIZ_REG(n) (0xC380 + (n <<= 2)) + +// +// Global Event Buffer Registers +// +#define DWC_XDCI_GEVNTADR_REG(n) (0xC400 + (n <<= 4)) +#define DWC_XDCI_EVNTSIZ_REG(n) (0xC408 + (n <<= 4)) +#define DWC_XDCI_EVNTSIZ_MASK (0x0000FFFF) +#define DWC_XDCI_EVNT_INTR_MASK (0x80000000) +#define DWC_XDCI_EVNTCOUNT_REG(n) (0xC40C + (n <<= 4)) +#define DWC_XDCI_EVNTCOUNT_MASK (0x0000FFFF) + +// +// Device Configuration Register and Bit Definitions +// +#define DWC_XDCI_DCFG_REG (0xC700) +#define DWC_XDCI_DCFG_LPM_CAPABLE_MASK (0x00400000) +#define DWC_XDCI_DCFG_DEV_ADDRESS_MASK (0x000003F8) +#define DWC_XDCI_DCFG_DEV_ADDRESS_BIT_POS (3) +#define DWC_XDCI_DCFG_DESIRED_DEV_SPEED_MASK (0x00000007) +#define DWC_XDCI_DCFG_DESIRED_SS_SPEED (0x00000004) +#define DWC_XDCI_DCFG_DESIRED_FS_SPEED (0x00000001) +#define DWC_XDCI_DCFG_DESIRED_HS_SPEED (0x00000000) + +// +// Device Control Register +// +#define DWC_XDCI_DCTL_REG (0xC704) +#define DWC_XDCI_DCTL_RUN_STOP_MASK (0x80000000) +#define DWC_XDCI_DCTL_RUN_STOP_BIT_POS (31) +#define DWC_XDCI_DCTL_CSFTRST_MASK (0x40000000) +#define DWC_XDCI_DCTL_CSFTRST_BIT_POS (30) +#define DWC_XDCI_DCTL_KEEP_CONNECT_MASK (0x00080000) +#define DWC_XDCI_DCTL_KEEP_CONNECT_BIT_POS (19) +#define DWC_XDCI_DCTL_CSFTRST_BIT_POS (30) +#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_MASK (0x000001E0) +#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_BIT_POS (5) +#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_NO_ACTION (1) +#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_SS_DISABLED (4) +#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_RX_DETECT (5) +#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_SS_INACTIVE (6) +#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_RECOVERY (8) +#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_COMPLIANCE (10) +#define DWC_XDCI_DCTL_STATE_CHANGE_REQ_REMOTE_WAKEUP (8) + +// +// Device Event Enable Register +// +#define DWC_XDCI_DEVTEN_REG (0xC708) +#define DWC_XDCI_DEVTEN_DISCONN_DET_EN_MASK (0x00000001) +#define DWC_XDCI_DEVTEN_RESET_DET_EN_MASK (0x00000002) +#define DWC_XDCI_DEVTEN_CONN_DONE_DET_EN_MASK (0x00000004) +#define DWC_XDCI_DEVTEN_LINK_STATE_CHANGE_DET_EN_MASK (0x00000008) +#define DWC_XDCI_DEVTEN_RESUME_WAKEUP_DET_EN_MASK (0x00000010) +#define DWC_XDCI_DEVTEN_HIBERNATION_REQ_EN_MASK (0x00000020) +#define DWC_XDCI_DEVTEN_U3L2L1_DET_EN_MASK (0x00000040) +#define DWC_XDCI_DEVTEN_SOF_DET_EN_MASK (0x00000080) +#define DWC_XDCI_DEVTEN_ERRATIC_ERR_DET_EN_MASK (0x00000200) +#define DWC_XDCI_DEVTEN_VNDR_DEV_TST_RX_DET_EN_MASK (0x00001000) + +#define DWC_XDCI_DEVTEN_DEVICE_INTS (DWC_XDCI_DEVTE= N_DISCONN_DET_EN_MASK | \ + DWC_XDCI_DEVTEN_RESET_DET_EN_MASK | DWC_XDCI_DEVTEN_CONN_DONE_DET_= EN_MASK | \ + DWC_XDCI_DEVTEN_LINK_STATE_CHANGE_DET_EN_MASK | DWC_XDCI_DEVTEN_RE= SUME_WAKEUP_DET_EN_MASK | \ + DWC_XDCI_DEVTEN_HIBERNATION_REQ_EN_MASK | DWC_XDCI_DEVTEN_U3L2L1_D= ET_EN_MASK | \ + DWC_XDCI_DEVTEN_ERRATIC_ERR_DET_EN_MASK) + +#define DWC_XDCI_EVENT_BUFF_BULK_STREAM_ID_MASK (0xFFFF0000) +#define DWC_XDCI_EVENT_BUFF_ISOCH_UFRAME_NUM_MASK (0xFFFF0000) +#define DWC_XDCI_EVENT_BUFF_EP_CMD_TYPE_MASK (0x0F000000) +#define DWC_XDCI_EVENT_BUFF_EP_XFER_RES_INDEX_MASK (0x007F0000) +#define DWC_XDCI_EVENT_BUFF_EP_XFER_ACTIVE_MASK (0x00008000) +#define DWC_XDCI_EVENT_BUFF_EP_CTRL_DATA_REQ_MASK (0x00001000) +#define DWC_XDCI_EVENT_BUFF_EP_CTRL_STATUS_REQ_MASK (0x00002000) +#define DWC_XDCI_EVENT_BUFF_EP_LST_MASK (0x00008000) +#define DWC_XDCI_EVENT_BUFF_EP_MISSED_ISOCH_MASK (0x00008000) +#define DWC_XDCI_EVENT_BUFF_EP_IOC_MASK (0x00004000) +#define DWC_XDCI_EVENT_BUFF_EP_LAST_PKT_MASK (0x00002000) +#define DWC_XDCI_EVENT_BUFF_EP_STREAM_NOT_FND_MASK (0x00002000) +#define DWC_XDCI_EVENT_BUFF_EP_STREAM_FND_MASK (0x00001000) +#define DWC_XDCI_EVENT_BUFF_EP_ERR_NO_RES_MASK (0x00001000) +#define DWC_XDCI_EVENT_BUFF_EP_INVALID_RES_MASK (0x00001000) + +#define DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK (0x000003C0) +#define DWC_XDCI_EVENT_BUFF_EP_EVENT_BIT_POS (6) +#define DWC_XDCI_EVENT_BUFF_EP_XFER_CMPLT (1) +#define DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS (2) +#define DWC_XDCI_EVENT_BUFF_EP_XFER_NOT_READY (3) +#define DWC_XDCI_EVENT_BUFF_EP_STREAM_EVENT (6) +#define DWC_XDCI_EVENT_BUFF_EP_CMD_CMPLT (7) + +#define DWC_XDCI_EVENT_BUFF_EP_NUM_MASK (0x0000003E) +#define DWC_XDCI_EVENT_BUFF_EP_NUM_BIT_POS (1) + +#define DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK (0x0000F000) + + +#define DWC_XDCI_EVENT_BUFF_DEV_HIRD_MASK (0x01E00000) +#define DWC_XDCI_EVENT_BUFF_DEV_HIRD_BIT_POS (21) +#define DWC_XDCI_EVENT_BUFF_DEV_SS_EVENT_MASK (0x00100000) +#define DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_MASK (0x000F0000) +#define DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_BIT_POS (16) + +#define DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK (0x00000F00) +#define DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS (8) +#define DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT (12) +#define DWC_XDCI_EVENT_BUFF_DEV_BUFF_OVFL_EVENT (11) +#define DWC_XDCI_EVENT_BUFF_DEV_CMD_CMPLT_EVENT (10) +#define DWC_XDCI_EVENT_BUFF_DEV_ERRATIC_ERR_EVENT (9) +#define DWC_XDCI_EVENT_BUFF_DEV_SOF_EVENT (7) +#define DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT (5) +#define DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT (4) +#define DWC_XDCI_EVENT_BUFF_DEV_STATE_CHANGE_EVENT (3) +#define DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT (2) +#define DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT (1) +#define DWC_XDCI_EVENT_BUFF_DEV_DISCONN_EVENT (0) + +#define DWC_XDCI_EVENT_DEV_MASK (0x00000001) + +// +// Device Status Register and Bit Definitions +// +#define DWC_XDCI_DSTS_REG (0xC70C) +#define DWC_XDCI_DSTS_DEV_CTRL_HALTED_MASK (0x00400000) +#define DWC_XDCI_DSTS_DEV_CTRL_HALTED_BIT_POS (22) +#define DWC_XDCI_DSTS_CORE_IDLE (1 << 23) +#define DWC_XDCI_DSTS_CONN_SPEED_MASK (0x00000007) +#define DWC_XDCI_DSTS_LINK_STATE_MASK (0x003C0000) +#define DWC_XDCI_DSTS_LINK_STATE_DISCONNECT (0x00100000) + +// +// Device Generic Command Parameter Register +// +#define DWC_XDCI_DGCMD_PARAM_REG (0xC710) +#define DWC_XDCI_DGCMD_PARAM_TX_FIFO_NUM_MASK (0x0000001F) +#define DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK (0x00000020) +#define DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_BIT_POS (5) + +// +// Device Generic Command Register +// +#define DWC_XDCI_DGCMD_REG (0xC714) +#define DWC_XDCI_DGCMD_CMD_STATUS_MASK (0x00008000) +#define DWC_XDCI_DGCMD_CMD_ACTIVE_MASK (0x00000400) +#define DWC_XDCI_DGCMD_CMD_IOC_MASK (0x00000100) +#define DWC_XDCI_DGCMD_CMD_TYPE_MASK (0x000000FF) +#define DWC_XDCI_DGCMD_CMD_SET_PERIODIC_PARAMS (0x2) +#define DWC_XDCI_DGCMD_CMD_SET_SCRATCH_PAD_BUFF_ARR_LO (0x4) +#define DWC_XDCI_DGCMD_CMD_SET_SCRATCH_PAD_BUFF_ARR_HI (0x5) +#define DWC_XDCI_DGCMD_CMD_XMIT_DEVICE_NOTIFICATION (0x7) +#define DWC_XDCI_DGCMD_CMD_SEL_FIFO_FLUSH (0x9) +#define DWC_XDCI_DGCMD_CMD_ALL_FIFO_FLUSH (0xA) +#define DWC_XDCI_DGCMD_CMD_SET_EP_NRDY (0xC) +#define DWC_XDCI_DGCMD_CMD_RUN_SOC_BUS_LPBK (0x10) + +// +// Device Active USB EP Enable Register +// +#define DWC_XDCI_EP_DALEPENA_REG (0xC720) + +// +// Device Physical EP CMD Param 2 Register. Value is 32-bit +// +#define DWC_XDCI_EPCMD_PARAM2_REG(n) (0xC800 + (n <<= 4)) + +// +// Device Physical EP CMD Param 1 Register. Value is 32-bit +// +#define DWC_XDCI_EPCMD_PARAM1_REG(n) (0xC804 + (n <<= 4)) + +// +// Device Physical EP CMD Param 0 Register. Value is 32-bit +// +#define DWC_XDCI_EPCMD_PARAM0_REG(n) (0xC808 + (n <<= 4)) + +// +// Device Physical EP Command Registers and Bit Definitions +// +#define DWC_XDCI_EPCMD_REG(n) (0xC80C + (n <<= 4)) +#define DWC_XDCI_EPCMD_RES_IDX_MASK (0x007F0000) +#define DWC_XDCI_EPCMD_RES_IDX_BIT_POS (16) +#define DWC_XDCI_EPCMD_CMDTYPE_MASK (0x0000000F) +#define DWC_XDCI_EPCMD_SET_EP_CONFIG (0x1) +#define DWC_XDCI_EPCMD_SET_EP_XFER_RES_CONFIG (0x2) +#define DWC_XDCI_EPCMD_GET_EP_STATE (0x3) +#define DWC_XDCI_EPCMD_SET_STALL (0x4) +#define DWC_XDCI_EPCMD_CLEAR_STALL (0x5) +#define DWC_XDCI_EPCMD_START_XFER (0x6) +#define DWC_XDCI_EPCMD_UPDATE_XFER (0x7) +#define DWC_XDCI_EPCMD_END_XFER (0x8) +#define DWC_XDCI_EPCMD_START_NEW_CONFIG (0x9) + +#define DWC_XDCI_EPCMD_CMD_IOC_MASK (0x00000100) +#define DWC_XDCI_EPCMD_CMD_ACTIVE_MASK (0x00000400) +#define DWC_XDCI_EPCMD_HIGH_PRIO_MASK (0x00000800) +#define DWC_XDCI_EPCMD_FORCE_RM_MASK (0x00000800) + +// +// Command status and parameter values same as event status and parameters= values +// +#define DWC_XDCI_EPCMD_CMD_STATUS_MASK (0x0000F000) + +// +// Command Params bit masks +// +#define DWC_XDCI_PARAM1_SET_EP_CFG_FIFO_BASED_MASK (0x80000000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_BULK_BASED_MASK (0x40000000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_MASK (0x3C000000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_MASK (0x02000000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK (0x01000000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_MASK (0x00FF0000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_BIT_POS (16) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EBC_MASK (0x00008000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK (0x00003F00) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_BIT_POS (8) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_STRM_MASK (0x00002000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_MASK (0x00000400) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_IN_PRG_MASK (0x00000200) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_CMPLT_MASK (0x00000100) +#define DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK (0x0000001F) + +// +// CMD 1 param 0 +// +#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MASK (0xC0000000) +#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_BIT_POS (30) +#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_INIT_STATE (0) +#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_RESTORE_ST (1) +#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE (2) +#define DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_NONE (3) +#define DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_MASK (0x03C00000) +#define DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_BIT_POS (22) +#define DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_MASK (0x003E0000) +#define DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_BIT_POS (17) +#define DWC_XDCI_PARAM0_SET_EP_CFG_MPS_MASK (0x00003FF8) +#define DWC_XDCI_PARAM0_SET_EP_CFG_MPS_BIT_POS (3) +#define DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_MASK (0x00000006) +#define DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_BIT_POS (1) +#define DWC_XDCI_PARAM0_EP_TYPE_CTRL (0) +#define DWC_XDCI_PARAM0_EP_TYPE_ISOCH (1) +#define DWC_XDCI_PARAM0_EP_TYPE_BULK (2) +#define DWC_XDCI_PARAM0_EP_TYPE_INTR (3) + +// +// CMD 1 param 1 +// +#define DWC_XDCI_PARAM1_SET_EP_CFG_BULK_BASED_MASK (0x40000000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_MASK (0x3C000000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_BIT_POS (26) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_MASK (0x02000000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_BIT_POS (25) +#define DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK (0x01000000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_MASK (0x00FF0000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_BIT_POS (16) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EBC_MASK (0x00008000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK (0x00003F00) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_BIT_POS (8) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_STRM_MASK (0x00002000) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_MASK (0x00000400) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_IN_PRG_MASK (0x00000200) +#define DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_CMPLT_MASK (0x00000100) +#define DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK (0x0000001F) + +// +// CMD 2 param 0 +// +#define DWC_XDCI_PARAM0_SET_EP_XFER_RES_NUM_MASK (0x0000FFFF) + +// +// CMD 3 param 2 +// +#define DWC_XDCI_PARAM2_GET_EP_STATE_MASK (0xFFFFFFFF) + +// +// CMD 6 param 1 +// +#define DWC_XDCI_PARAM1_STRT_XFER_TD_ADDR_LO_MASK (0xFFFFFFFF) + +// +// CMD 6 param 0 +// +#define DWC_XDCI_PARAM0_STRT_XFER_TD_ADDR_HI_MASK (0xFFFFFFFF) + +// +// Transfer Request Block Fields' Bit Definitions +// +#define DWC_XDCI_TRB_BUFF_SIZE_MASK (0x00FFFFFF) +#define DWC_XDCI_TRB_PCM1_MASK (0x03000000) +#define DWC_XDCI_TRB_PCM1_BIT_POS (24) +#define DWC_XDCI_TRB_STATUS_MASK (0xF0000000) +#define DWC_XDCI_TRB_STATUS_BIT_POS (28) +#define DWC_XDCI_TRB_STATUS_OK (0) +#define DWC_XDCI_TRB_STATUS_MISSED_ISOCH (1) +#define DWC_XDCI_TRB_STATUS_SETUP_PENDING (2) + +#define DWC_XDCI_TRB_CTRL_HWO_MASK (0x00000001) +#define DWC_XDCI_TRB_CTRL_LST_TRB_MASK (0x00000002) +#define DWC_XDCI_TRB_CTRL_LST_TRB_BIT_POS (1) +#define DWC_XDCI_TRB_CTRL_CHAIN_BUFF_MASK (0x00000004) +#define DWC_XDCI_TRB_CTRL_CHAIN_BUFF_BIT_POS (2) +#define DWC_XDCI_TRB_CTRL_CSP_MASK (0x00000008) +#define DWC_XDCI_TRB_CTRL_CSP_BIT_POS (3) +#define DWC_XDCI_TRB_CTRL_TYPE_MASK (0x000003F0) +#define DWC_XDCI_TRB_CTRL_TYPE_BIT_POS (4) +#define DWC_XDCI_TRB_CTRL_TYPE_NORMAL (1) +#define DWC_XDCI_TRB_CTRL_TYPE_SETUP (2) +#define DWC_XDCI_TRB_CTRL_TYPE_STATUS2 (3) +#define DWC_XDCI_TRB_CTRL_TYPE_STATUS3 (4) +#define DWC_XDCI_TRB_CTRL_TYPE_DATA (5) +#define DWC_XDCI_TRB_CTRL_TYPE_ISOCH_FIRST (6) +#define DWC_XDCI_TRB_CTRL_TYPE_ISOCH (7) +#define DWC_XDCI_TRB_CTRL_TYPE_LINK_TRB (8) +#define DWC_XDCI_TRB_CTRL_IOSP_MISOCH_MASK (0x00000400) +#define DWC_XDCI_TRB_CTRL_IOSP_MISOCH_BIT_POS (10) +#define DWC_XDCI_TRB_CTRL_IOC_MASK (0x00000800) +#define DWC_XDCI_TRB_CTRL_IOC_BIT_POS (11) +#define DWC_XDCI_TRB_CTRL_STRM_ID_SOF_NUM_MASK (0x3FFFC000) +#define DWC_XDCI_TRB_CTRL_STRM_ID_SOF_BIT_POS (14) + +#define DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES (4) +#define DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES (12) + +typedef enum { + EPCMD_SET_EP_CONFIG =3D 1, + EPCMD_SET_EP_XFER_RES_CONFIG, + EPCMD_GET_EP_STATE, + EPCMD_SET_STALL, + EPCMD_CLEAR_STALL, + EPCMD_START_XFER, + EPCMD_UPDATE_XFER, + EPCMD_END_XFER, + EPCMD_START_NEW_CONFIG =3D 9 +} DWC_XDCI_ENDPOINT_CMD; + +typedef enum { + ON =3D 0, + SLEEP =3D 2, + SUSPEND, + DISCONNECTED, + EARLY_SUSPEND, + RESET =3D 14, + RESUME =3D 15 +} DWC_XDCI_HS_LINK_STATE; + +typedef enum { + TRBCTL_NORMAL =3D 1, + TRBCTL_SETUP, + TRBCTL_2_PHASE, + TRBCTL_3_PHASE, + TRBCTL_CTRL_DATA_PHASE, + TRBCTL_ISOCH_FIRST, + TRBCTL_ISOCH, + TRBCTL_LINK +} DWC_XDCI_TRB_CONTROL; + +// +// DWC XDCI Endpoint Commands Parameters struct +// +typedef struct { + UINT32 Param2; + UINT32 Param1; + UINT32 Param0; +} DWC_XDCI_ENDPOINT_CMD_PARAMS; + +// +// Event Buffer Struct +// +typedef struct { + UINT32 Event; + UINT32 DevTstLmp1; + UINT32 DevTstLmp2; + UINT32 Reserved; +} DWC_XDCI_EVENT_BUFFER; + +// +// Transfer Request Block +// +typedef struct { + UINT32 BuffPtrLow; + UINT32 BuffPtrHigh; + UINT32 LenXferParams; + UINT32 TrbCtrl; +} DWC_XDCI_TRB; + +typedef struct { + USB_EP_INFO EpInfo; + DWC_XDCI_TRB *Trb; + USB_XFER_REQUEST XferHandle; + UINT32 CurrentXferRscIdx; + VOID *CoreHandle; + USB_EP_STATE State; + USB_EP_STATE OrgState; + BOOLEAN CheckFlag; +} DWC_XDCI_ENDPOINT; + +typedef struct { + // + // CbEventParams must be copied over by upper layer if + // it defers event processing + // + USB_DEVICE_CALLBACK_PARAM CbEventParams; + + // + // Callback function list + // + USB_DEVICE_CALLBACK_FUNC DevDisconnectCallback; + USB_DEVICE_CALLBACK_FUNC DevBusResetCallback; + USB_DEVICE_CALLBACK_FUNC DevResetDoneCallback; + USB_DEVICE_CALLBACK_FUNC DevLinkStateCallback; + USB_DEVICE_CALLBACK_FUNC DevWakeupCallback; + USB_DEVICE_CALLBACK_FUNC DevHibernationCallback; + USB_DEVICE_CALLBACK_FUNC DevSofCallback; + USB_DEVICE_CALLBACK_FUNC DevErraticErrCallback; + USB_DEVICE_CALLBACK_FUNC DevCmdCmpltCallback; + USB_DEVICE_CALLBACK_FUNC DevBuffOvflwCallback; + USB_DEVICE_CALLBACK_FUNC DevTestLmpRxCallback; + USB_DEVICE_CALLBACK_FUNC DevSetupPktReceivedCallback; + USB_DEVICE_CALLBACK_FUNC DevXferNrdyCallback; + USB_DEVICE_CALLBACK_FUNC DevXferDoneCallback; +} USB_DEV_CALLBACK_LIST; + +typedef struct { + VOID *ParentHandle; = // Pointer to the parent this driver is associated + USB_CONTROLLER_ID Id; = // ID of the controllers supported in our DCD + USB_SPEED DesiredSpeed; = // Desired SS, HS, FS or LS Speeds for the core + USB_ROLE Role; = // Desired role i.e. host, Device or OTG + USB_SPEED ActualSpeed; = // Actual Speed + USB_DEVICE_STATE DevState; = // Device state + UINT32 BaseAddress; = // Register Base address + UINT32 Flags; = // Init flags + UINT32 MaxDevIntLines; = // One event Buffer per interrupt line + DWC_XDCI_EVENT_BUFFER EventBuffers [DWC_XDCI_MAX_EVENTS_PER_BUFFER * = 2]; // Event Buffer pool + DWC_XDCI_EVENT_BUFFER *AlignedEventBuffers; = // Aligned event Buffer pool + DWC_XDCI_EVENT_BUFFER *CurrentEventBuffer; = // Current event Buffer address + DWC_XDCI_TRB UnalignedTrbs [(DWC_XDCI_MAX_ENDPOINTS + 1) * D= WC_XDCI_TRB_NUM]; // TRBs. + DWC_XDCI_TRB *Trbs; = // 16-bytes aligned TRBs. + DWC_XDCI_ENDPOINT EpHandles [DWC_XDCI_MAX_ENDPOINTS]; = // EPs + UINT8 DefaultSetupBuffer [DWC_XDCI_SETUP_BUFF_SIZE * = 2]; // Unaligned setup Buffer + UINT8 *AlignedSetupBuffer; = // Aligned setup Buffer. Aligned to 8-byte boundary + UINT8 MiscBuffer [528]; = // Unaligned misc Buffer + UINT8 *AlignedMiscBuffer; = // Aligned misc Buffer + UINT32 LinkState; = // Link state + UINT32 HirdVal; = // HIRD value + USB_DEV_CALLBACK_LIST EventCallbacks; + volatile BOOLEAN InterrupProcessing; +} XDCI_CORE_HANDLE; + +// +// DWC XDCI API prototypes +// +EFI_STATUS +EFIAPI +DwcXdciCoreInit ( + IN USB_DEV_CONFIG_PARAMS *ConfigParams, + IN VOID *ParentHandle, + IN VOID **CoreHandle + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreDeinit ( + IN VOID *CoreHandle, + IN UINT32 flags + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreRegisterCallback ( + IN VOID *CoreHandle, + IN USB_DEVICE_EVENT_ID Event, + IN USB_DEVICE_CALLBACK_FUNC CallbackFunc + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreUnregisterCallback ( + IN VOID *CoreHandle, + IN USB_DEVICE_EVENT_ID Event + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreIsrRoutine ( + IN VOID *CoreHandle + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreIsrRoutineTimerBased ( + IN VOID *CoreHandle + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreConnect ( + IN VOID *CoreHandle + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreDisconnect ( + IN VOID *CoreHandle + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreGetSpeed ( + IN VOID *CoreHandle, + IN USB_SPEED *Speed + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreSetAddress ( + IN VOID *CoreHandle, + IN UINT32 Address + ); + +EFI_STATUS +EFIAPI +DwcXdciCoreSetConfig ( + IN VOID *CoreHandle, + IN UINT32 ConfigNum + ); + +EFI_STATUS +EFIAPI +DwcXdciSetLinkState ( + IN VOID *CoreHandle, + IN USB_DEVICE_SS_LINK_STATE State + ); + +EFI_STATUS +EFIAPI +DwcXdciInitEp ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +EFIAPI +DwcXdciEpEnable ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +EFIAPI +DwcXdciEpDisable ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +EFIAPI +DwcXdciEpStall ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +EFIAPI +DwcXdciEpClearStall ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +EFIAPI +DwcXdciEpSetNrdy ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +EFIAPI +DwcXdciEp0ReceiveSetupPkt ( + IN VOID *CoreHandle, + IN UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +DwcXdciEp0ReceiveStatusPkt ( + IN VOID *CoreHandle + ); + +EFI_STATUS +EFIAPI +DwcXdciEp0SendStatusPkt ( + IN VOID *CoreHandle + ); + +EFI_STATUS +EFIAPI +DwcXdciEpTxData ( + IN VOID *CoreHandle, + IN USB_XFER_REQUEST *XferReq + ); + +EFI_STATUS +EFIAPI +DwcXdciEpRxData( + IN VOID *CoreHandle, + IN USB_XFER_REQUEST *XferReq + ); + +EFI_STATUS +EFIAPI +DwcXdciEpCancelTransfer ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +usbProcessDeviceResetDet ( + IN XDCI_CORE_HANDLE *CoreHandle + ); + +EFI_STATUS +usbProcessDeviceResetDone ( + IN XDCI_CORE_HANDLE *CoreHandle + ); + +UINT32 +UsbGetPhysicalEpNum ( + IN UINT32 EndpointNum, + IN USB_EP_DIR EndpointDir + ); + +UINT32 +UsbRegRead ( + IN UINT32 Base, + IN UINT32 Offset + ); + +VOID +UsbRegWrite ( + IN UINT32 Base, + IN UINT32 Offset, + IN UINT32 val + ); + +EFI_STATUS +UsbXdciCoreFlushEpFifo ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciD= evice.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDevi= ce.c new file mode 100644 index 0000000..2dcd448 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDevice.c @@ -0,0 +1,695 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include +#include "XdciCommon.h" +#include "XdciDevice.h" +#include "XdciInterface.h" +#include "UsbDeviceMode.h" + +/** + This function is used to initialize the device controller + @configParams: Parameters from app to configure the core + @DevCoreHandle: Return parameter for upper layers to use + for all HW-independent APIs + +**/ +EFI_STATUS +UsbDeviceInit ( + IN USB_DEV_CONFIG_PARAMS *ConfigParams, + IN OUT VOID **DevCoreHandle + ) +{ + USB_DEV_CORE *DevCorePtr; + EFI_STATUS Status =3D EFI_INVALID_PARAMETER; + + DEBUG ((DEBUG_INFO, "Call UsbDeviceInit start\n")); + + // + // Allocate device handle + // + DevCorePtr =3D AllocateZeroPool (sizeof (USB_DEV_CORE)); + DEBUG ((DEBUG_INFO, "device handle =3D 0x%x\n", DevCorePtr)); + + if (DevCorePtr =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceInit. ERROR: Failed to allocate memory\n= ")); + return EFI_OUT_OF_RESOURCES; + } + + DEBUG ((DEBUG_INFO, "call UsbDeviceGetCoreDriver, ID=3D%x, \n", ConfigPa= rams->ControllerId)); + + // + // Get the driver for this USB device core + // + DevCorePtr->CoreDriver =3D UsbDeviceGetCoreDriver(ConfigParams->Controll= erId); + if (DevCorePtr->CoreDriver !=3D NULL) { + DEBUG ((DEBUG_INFO, "call DevCoreInit\n")); + Status =3D DevCorePtr->CoreDriver->DevCoreInit( + ConfigParams, + (VOID*)DevCorePtr, + &DevCorePtr->ControllerHandle); + } else { + DEBUG ((DEBUG_INFO, "UsbDeviceInit. ERROR: Driver not found\n")); + return EFI_INVALID_PARAMETER; + } + + *DevCoreHandle =3D (VOID *)DevCorePtr; + return Status; +} + +/** + This function is used to de-initialize the device controller + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @flags: Flags indicating what type of de-initialization is required + +**/ +EFI_STATUS +UsbDeviceDeinit ( + IN VOID *DevCoreHandle, + IN UINT32 Flags + ) +{ + USB_DEV_CORE *Core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (Core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceDeinit: ERROR: INVALID HANDLE\n")); + } else { + if (Core->CoreDriver !=3D NULL) { + Status =3D Core->CoreDriver->DevCoreDeinit( + Core->ControllerHandle, + Flags + ); + FreePool(DevCoreHandle); + } else { + DEBUG ((DEBUG_INFO, "UsbDeviceDeinit: Driver not found\n")); + Status =3D EFI_INVALID_PARAMETER; + } + } + + return Status; +} + +/** + This function is used to register callback function for + specified event + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @event: Event for which callback is to be registered + @callbackFn: Callback function to be called by the + controller driver for above event after critical processing + +**/ +EFI_STATUS +UsbDeviceRegisterCallback ( + IN VOID *DevCoreHandle, + IN USB_DEVICE_EVENT_ID EventId, + IN USB_DEVICE_CALLBACK_FUNC CallbackFunc + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + + DEBUG ((DEBUG_INFO, "UsbDeviceRegisterCallback start\n")); + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceRegisterCallback: ERROR: INVALID HANDLE\= n")); + } else { + if (core->CoreDriver !=3D NULL) { + DEBUG ((DEBUG_INFO, "Call DevCoreRegisterCallback\n")); + Status =3D core->CoreDriver->DevCoreRegisterCallback ( + core->ControllerHandle, + EventId, + CallbackFunc + ); + } + } + + return Status; +} + +/** + This function is used to register callback function for + specified event + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @eventId: Event for which callback is to be unregistered + +**/ +EFI_STATUS +UsbDeviceUnregisterCallback ( + IN VOID *DevCoreHandle, + IN USB_DEVICE_EVENT_ID EventId + ) +{ + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceUnregisterCallback: ERROR: INVALID HANDL= E\n")); + } else { + if (core->CoreDriver !=3D NULL) { + Status =3D core->CoreDriver->DevCoreUnregisterCallback( + core->ControllerHandle, + EventId + ); + } + } + + return Status; +} + +/** + This function is used to service interrupt events on device + controller. Use this API in your OS/stack-specific ISR framework + In polled mode scenario, invoke this API in a loop to service the + events + @DevCoreHandle: Handle to HW-independent APIs for device + controller + +**/ +EFI_STATUS +UsbDeviceIsrRoutine ( + IN VOID *DevCoreHandle + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceIsrRoutine: ERROR: INVALID HANDLE\n")); + } else { + if (core->CoreDriver !=3D NULL) { + Status =3D core->CoreDriver->DevCoreIsrRoutine (core->ControllerHand= le); + } + } + + return Status; +} + + +/** + This function is used to service interrupt events on device + controller. Use this API in your OS/stack-specific ISR framework + In polled mode scenario, invoke this API in a loop to service the + events + @DevCoreHandle: Handle to HW-independent APIs for device + controller + +**/ +EFI_STATUS +UsbDeviceIsrRoutineTimerBased ( + IN VOID *DevCoreHandle + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceIsrRoutine: ERROR: INVALID HANDLE\n")); + } else { + if (core->CoreDriver !=3D NULL) { + Status =3D core->CoreDriver->DevCoreIsrRoutineTimerBased (core->Cont= rollerHandle); + } + } + + return Status; +} + + +/** + This function is used to enable device controller to connect + to USB host + @DevCoreHandle: Handle to HW-independent APIs for device + controller + +**/ +EFI_STATUS +UsbXdciDeviceConnect ( + IN VOID *DevCoreHandle + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbXdciDeviceConnect: ERROR: INVALID HANDLE\n")); + } else { + DEBUG ((DEBUG_INFO, "UsbXdciDeviceConnect\n")); + Status =3D core->CoreDriver->DevCoreConnect (core->ControllerHandle); + } + + return Status; +} + +/** + This function is used to disconnect device controller + from USB host + @DevCoreHandle: Handle to HW-independent APIs for device + controller + +**/ +EFI_STATUS +UsbDeviceDisconnect ( + IN VOID *DevCoreHandle + ) +{ + USB_DEV_CORE *core =3D(USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceDisconnect: ERROR: INVALID HANDLE\n")); + } else { + DEBUG ((DEBUG_INFO, "UsbDeviceDisconnect\n")); + Status =3D core->CoreDriver->DevCoreDisconnect(core->ControllerHandle)= ; + } + + return Status; +} + +/** + This function is used to obtain USB bus Speed after bus reset complete + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @Speed: negotiated Speed + +**/ +EFI_STATUS +UsbDeviceGetSpeed ( + IN VOID *DevCoreHandle, + IN USB_SPEED *Speed + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceGetSpeed: ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreGetSpeed(core->ControllerHandle, S= peed); + } + + return Status; +} + +/** + This function is used to set USB device address + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @address: USB device address to set + +**/ +EFI_STATUS +UsbDeviceSetAddress ( + IN VOID *DevCoreHandle, + IN UINT32 Address + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + DEBUG ((DEBUG_INFO, "UsbDeviceSetAddress: enter......\n")); + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceSetAddress: ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreSetAddress(core->ControllerHandle,= Address); + } + DEBUG ((DEBUG_INFO, "UsbDeviceSetAddress: exit......\n")); + + return Status; +} + +/** + This function is used to do device controller-specific processing + of set configuration device framework request + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @ConfigNum: configuration number selected by USB host + +**/ +EFI_STATUS +UsbDeviceSetConfiguration ( + IN VOID *DevCoreHandle, + IN UINT32 ConfigNum + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceSetConfiguration: ERROR: INVALID HANDLE\= n")); + } else { + Status =3D core->CoreDriver->DevCoreSetConfig (core->ControllerHandle,= ConfigNum); + } + + return Status; +} + +/** + This function is used to set desired link state in device controller + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @state: Desired link state + +**/ +EFI_STATUS +UsbDeviceSetLinkState ( + IN VOID *DevCoreHandle, + IN USB_DEVICE_SS_LINK_STATE State + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceSetLinkState: ERROR: INVALID HANDLE\n"))= ; + } else { + Status =3D core->CoreDriver->DevCoreSetLinkState (core->ControllerHand= le, State); + } + + return Status; +} + +/** + This function is used to initialize non-EP0 endpoints + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @EpInfo: Endpoint information for EP to be initialized + +**/ +EFI_STATUS +UsbDeviceInitEp ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceInitEp: ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreInitEp (core->ControllerHandle, Ep= Info); + } + + return Status; +} + +/** + This function is used to enable an endpoint + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @EpInfo: Endpoint information for EP to be enabled + +**/ +EFI_STATUS +UsbDeviceEpEnable ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceEpEnable: ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEpEnable (core->ControllerHandle, = EpInfo); + } + + return Status; +} + +/** + This function is used to disable an endpoint + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @EpInfo: Endpoint information for EP to be disabled + +**/ +EFI_STATUS +UsbDeviceEpDisable ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceEpDisable ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEpDisable (core->ControllerHandle,= EpInfo); + } + + return Status; +} + +/** + This function is used to STALL an endpoint + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @EpInfo: Endpoint information for EP to be stalled + +**/ +EFI_STATUS +UsbDeviceEpStall ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceEpStall ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEpStall (core->ControllerHandle, E= pInfo); + } + + return Status; +} + +/** + This function is used to clear STALL on an endpoint + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @EpInfo: Endpoint information for which STALL needs to be cleared + +**/ +EFI_STATUS +UsbDeviceEpClearStall ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceEpClearStall ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEpClearStall (core->ControllerHand= le, EpInfo); + } + + return Status; +} + +/** + This function is used to set EP not ready state + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @EpInfo: Endpoint information for EP that needs to be + set in not ready state + +**/ +EFI_STATUS +UsbDeviceEpSetNrdy ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceEpSetNrdy ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEpSetNrdy (core->ControllerHandle,= EpInfo); + } + + return Status; +} + +/** + This function is used to queue request to receive SETUP packet + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @Buffer: Buffer (bus-width aligned) where SETUP packet + needs to be received + +**/ +EFI_STATUS +UsbDeviceEp0RxSetup ( + IN VOID *DevCoreHandle, + IN UINT8 *Buffer + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceEp0RxSetup ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEp0RxSetupPkt (core->ControllerHan= dle, Buffer); + } + + return Status; +} + +/** + This function is used to queue request to receive status phase + for control transfer on EP0 + @DevCoreHandle: Handle to HW-independent APIs for device + controller + +**/ +EFI_STATUS +UsbDeviceEp0RxStatus ( + IN VOID *DevCoreHandle + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceEp0RxStatus ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEp0RxStatusPkt (core->ControllerHa= ndle); + } + return Status; +} + +/** + This function is used to queue request to send status phase for + control transfer on EP0 + @DevCoreHandle: Handle to HW-independent APIs for device + controller + +**/ +EFI_STATUS +UsbDeviceEp0TxStatus ( + IN VOID *DevCoreHandle + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceEp0TxStatus ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEp0TxStatusPkt (core->ControllerHa= ndle); + } + + return Status; +} + +/** + This function is used to queue a single request to transmit data on + an endpoint. If more than one request need to be queued before + previous requests complete then a request queue needs to be + implemented in upper layers. This API should be not be invoked until + current request completes. + Callback for transfer completion is invoked when requested transfer leng= th + is reached or if a short packet is received + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @XferReq: Address to transfer request describing this transfer + +**/ +EFI_STATUS +UsbXdciDeviceEpTxData ( + IN VOID *DevCoreHandle, + IN USB_XFER_REQUEST *XferReq + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbXdciDeviceEpTxData ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEpTxData (core->ControllerHandle, = XferReq); + } + + return Status; +} + +/** + This function is used to queue a single request to receive data on + an endpoint. If more than one request need to be queued before + previous requests complete then a request queue needs to be implemented + in upper layers. This API should be not be invoked until current request + completes. + Callback for transfer completion is invoked when requested transfer leng= th + is reached or if a short packet is received + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @XferReq: Address to transfer request describing this transfer + +**/ +EFI_STATUS +UsbXdciDeviceEpRxData ( + IN VOID *DevCoreHandle, + IN USB_XFER_REQUEST *XferReq + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbXdciDeviceEpRxData ERROR: INVALID HANDLE\n")); + } else { + Status =3D core->CoreDriver->DevCoreEpRxData (core->ControllerHandle, = XferReq); + } + + return Status; +} + +/** + This function is used to cancel a transfer request that was + previously queued on an endpoint + @DevCoreHandle: Handle to HW-independent APIs for device + controller + @EpInfo: Endpoint info where transfer needs to be cancelled + +**/ +EFI_STATUS +UsbDeviceEpCancelTransfer ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ) +{ + USB_DEV_CORE *core =3D (USB_DEV_CORE *)DevCoreHandle; + EFI_STATUS Status =3D EFI_DEVICE_ERROR; + + if (core =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "UsbDeviceEpCancelTransfer ERROR: INVALID HANDLE\n= ")); + } else { + Status =3D core->CoreDriver->DevCoreEpCancelTransfer (core->Controller= Handle, EpInfo); + } + + return Status; +} + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciD= evice.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDevi= ce.h new file mode 100644 index 0000000..aee6bde --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDevice.h @@ -0,0 +1,184 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef _USB_DEVICE_H_ +#define _USB_DEVICE_H_ + +// +// @USB_DEV_CONFIG_PARAMS: Struct to be filled in with configuration +// parameters and passed to the init routine for device controller +// +typedef struct { + USB_CONTROLLER_ID ControllerId; // Controller ID of the core + UINT32 BaseAddress; // Base address of the controller regis= ters and on-chip memory + UINT32 Flags; // Initialization flags + USB_SPEED Speed; // Desired USB bus Speed + USB_ROLE Role; // Default USB role +} USB_DEV_CONFIG_PARAMS; + +// +// @USB_DEV_CORE: Struct used as a handle for all +// hardware-independent APIs +// +typedef struct { + const struct UsbDeviceCoreDriver *CoreDriver; + VOID *ControllerHandle; +} USB_DEV_CORE; + +typedef +EFI_STATUS +(EFIAPI *USB_DEVICE_CALLBACK_FUNC) ( + IN USB_DEVICE_CALLBACK_PARAM *Param + ); + +EFI_STATUS +UsbDeviceInit ( + IN USB_DEV_CONFIG_PARAMS *ConfigParams, + IN OUT VOID **DevCoreHandle + ); + +EFI_STATUS +UsbDeviceDeinit ( + IN VOID *DevCoreHandle, + IN UINT32 Flags + ); + +EFI_STATUS +UsbDeviceRegisterCallback ( + IN VOID *DevCoreHandle, + IN USB_DEVICE_EVENT_ID EventId, + IN USB_DEVICE_CALLBACK_FUNC CallbackFunc + ); + +EFI_STATUS +UsbDeviceUnregisterCallback ( + IN VOID *DevCoreHandle, + IN USB_DEVICE_EVENT_ID EventId + ); + +EFI_STATUS +UsbDeviceIsrRoutine ( + IN VOID *DevCoreHandle + ); + +EFI_STATUS +UsbDeviceIsrRoutineTimerBased ( + IN VOID *DevCoreHandle + ); + +EFI_STATUS +UsbXdciDeviceConnect ( + IN VOID *DevCoreHandle + ); + +EFI_STATUS +UsbDeviceDisconnect ( + IN VOID *DevCoreHandle + ); + +EFI_STATUS +UsbDeviceGetSpeed ( + IN VOID *DevCoreHandle, + IN USB_SPEED *Speed + ); + +EFI_STATUS +UsbDeviceSetLinkState ( + IN VOID *DevCoreHandle, + IN USB_DEVICE_SS_LINK_STATE State + ); + +EFI_STATUS +UsbDeviceSetAddress ( + IN VOID *DevCoreHandle, + IN UINT32 Address + ); + +EFI_STATUS +UsbDeviceSetConfiguration ( + IN VOID *DevCoreHandle, + IN UINT32 ConfigNum + ); + +EFI_STATUS +UsbDeviceInitEp ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +UsbDeviceEpEnable ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +UsbDeviceEpDisable ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +UsbDeviceEpStall ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +UsbDeviceEpClearStall ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +UsbDeviceEpSetNrdy ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ); + +EFI_STATUS +UsbDeviceEp0RxSetup ( + IN VOID *DevCoreHandle, + IN UINT8 *Buffer + ); + +EFI_STATUS +UsbDeviceEp0RxStatus ( + IN VOID *DevCoreHandle + ); + +EFI_STATUS +UsbDeviceEp0TxStatus ( + IN VOID *DevCoreHandle + ); + +EFI_STATUS +UsbXdciDeviceEpTxData ( + IN VOID *DevCoreHandle, + IN USB_XFER_REQUEST *XferReq + ); + +EFI_STATUS +UsbXdciDeviceEpRxData ( + IN VOID *DevCoreHandle, + IN USB_XFER_REQUEST *XferReq + ); + +EFI_STATUS +UsbDeviceEpCancelTransfer ( + IN VOID *DevCoreHandle, + IN USB_EP_INFO *EpInfo + ); + +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciI= nterface.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciI= nterface.h new file mode 100644 index 0000000..90264e8 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciInterfac= e.h @@ -0,0 +1,241 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef _USB_DCD_IF_H_ +#define _USB_DCD_IF_H_ + +/* Core driver for device controller + * @DevCoreInit: Intializes device controller + * @DevCoreDeinit: De-initializes device controller + * @DevCoreRegisterCallback: Registers callback function for + * an event to be called by the controller driver + * @DevCoreUnregisterCallback: Unregisters callback function + * for an event + * @DevCoreIsrRoutine: core interrupt service routine for + * device controller to be used by OS/stack-i/f layer + * @DevCoreConnect: Enable device controller to connect to USB host + * @DevCoreDisconnect: Soft disconnect device controller from + * USB host + * @DevCoreGetSpeed: Get USB bus Speed on which device controller + * is attached + * @DevCoreSetAddress: Set USB device address in device controller + * @DevCoreSetConfig: Set configuration number for device controller + * @DevCoreSetLinkState: Set link state for device controller + * @DevCoreInitEp: Initialize non-EP0 endpoint + * @DevCoreEpEnable: Enable endpoint + * @DevCoreEpDisable: Disable endpoint + * @DevCoreEpStall: Stall/Halt endpoint + * @DevCoreEpClearStall: Clear Stall/Halt on endpoint + * @DevCoreEpSetNrdy: Set endpoint to not ready state + * @DevCoreEp0RxSetupPkt: Receive SETUP packet on EP0 + * @DevCoreEp0RxStatusPkt: Receive status packet on EP0 + * @DevCoreEp0TxStatusPkt: Transmit status packet from EP0 + * @DevCoreEpTxData: Transmit data from EP + * @DevCoreEpRxData: Received data on EP + * @DevCoreEpCancelTransfer: Cancel transfer on EP + */ + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_INIT) ( + IN USB_DEV_CONFIG_PARAMS *ConfigParams, + IN VOID *ParentHandle, + IN VOID **CoreHandle + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_DEINIT) ( + IN VOID *CoreHandle, + IN UINT32 Flags + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_REG_CALLBACK) ( + IN VOID *CoreHandle, + IN USB_DEVICE_EVENT_ID Event, + IN EFI_STATUS (*callbackFn)(IN USB_DEVICE_CALLBACK_PARAM = *CbEventParams) + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_UNREG_CALLBACK) ( + IN VOID *CoreHandle, + IN USB_DEVICE_EVENT_ID Event + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_ISR_ROUTINE) ( + IN VOID *CoreHandle + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_CONNECT) ( + IN VOID *CoreHandle + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_DISCONNECT) ( + IN VOID *CoreHandle + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_GET_SPEED) ( + IN VOID *CoreHandle, + IN USB_SPEED *Speed + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_SET_ADDRESS) ( + IN VOID *CoreHandle, + IN UINT32 Address + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_SET_CONFIG) ( + IN VOID *CoreHandle, + IN UINT32 ConfigNum + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_SET_LINK_STATE) ( + IN VOID *CoreHandle, + IN USB_DEVICE_SS_LINK_STATE State + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_INIT_EP) ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP_ENABLE) ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP_DISABLE) ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP_STALL) ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP_CLEAR_STALL) ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP_SET_NRDY) ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP0_RX_SETUP_PKT) ( + IN VOID *CoreHandle, + IN UINT8 *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP0_RX_STATUS_PKT) ( + IN VOID *CoreHandle + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP0_TX_STATUS_PKT) ( + IN VOID *CoreHandle + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP_TX_DATA) ( + IN VOID *CoreHandle, + IN USB_XFER_REQUEST *XferHandle + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP_RX_DATA) ( + IN VOID *CoreHandle, + IN USB_XFER_REQUEST *XferHandle + ); + +typedef +EFI_STATUS +(EFIAPI *DEV_CORE_EP_CANCEL_TRANSFER) ( + IN VOID *CoreHandle, + IN USB_EP_INFO *EpInfo + ); + +struct UsbDeviceCoreDriver { + DEV_CORE_INIT DevCoreInit; + DEV_CORE_DEINIT DevCoreDeinit; + DEV_CORE_REG_CALLBACK DevCoreRegisterCallback; + DEV_CORE_UNREG_CALLBACK DevCoreUnregisterCallback; + DEV_CORE_ISR_ROUTINE DevCoreIsrRoutine; + DEV_CORE_ISR_ROUTINE DevCoreIsrRoutineTimerBased; + DEV_CORE_CONNECT DevCoreConnect; + DEV_CORE_DISCONNECT DevCoreDisconnect; + DEV_CORE_GET_SPEED DevCoreGetSpeed; + DEV_CORE_SET_ADDRESS DevCoreSetAddress; + DEV_CORE_SET_CONFIG DevCoreSetConfig; + DEV_CORE_SET_LINK_STATE DevCoreSetLinkState; + DEV_CORE_INIT_EP DevCoreInitEp; + DEV_CORE_EP_ENABLE DevCoreEpEnable; + DEV_CORE_EP_DISABLE DevCoreEpDisable; + DEV_CORE_EP_STALL DevCoreEpStall; + DEV_CORE_EP_CLEAR_STALL DevCoreEpClearStall; + DEV_CORE_EP_SET_NRDY DevCoreEpSetNrdy; + DEV_CORE_EP0_RX_SETUP_PKT DevCoreEp0RxSetupPkt; + DEV_CORE_EP0_RX_STATUS_PKT DevCoreEp0RxStatusPkt; + DEV_CORE_EP0_TX_STATUS_PKT DevCoreEp0TxStatusPkt; + DEV_CORE_EP_TX_DATA DevCoreEpTxData; + DEV_CORE_EP_RX_DATA DevCoreEpRxData; + DEV_CORE_EP_CANCEL_TRANSFER DevCoreEpCancelTransfer; +}; + +// +// This API is used to obtain the driver handle for HW-independent API +// @id: The ID of the core for which this driver is requested +// +const struct UsbDeviceCoreDriver *UsbDeviceGetCoreDriver( + USB_CONTROLLER_ID id); + +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciT= able.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciTable= .c new file mode 100644 index 0000000..31990ae --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciTable.c @@ -0,0 +1,55 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include +#include "XdciCommon.h" +#include "XdciDevice.h" +#include "XdciInterface.h" +#include "XdciDWC.h" +#include "UsbDeviceMode.h" + +static const struct UsbDeviceCoreDriver CoreDriverTbl[USB_CORE_ID_MAX] =3D= { + DwcXdciCoreInit, + DwcXdciCoreDeinit, + DwcXdciCoreRegisterCallback, + DwcXdciCoreUnregisterCallback, + DwcXdciCoreIsrRoutine, + DwcXdciCoreIsrRoutineTimerBased, + DwcXdciCoreConnect, + DwcXdciCoreDisconnect, + DwcXdciCoreGetSpeed, + DwcXdciCoreSetAddress, + DwcXdciCoreSetConfig, + DwcXdciSetLinkState, + DwcXdciInitEp, + DwcXdciEpEnable, + DwcXdciEpDisable, + DwcXdciEpStall, + DwcXdciEpClearStall, + DwcXdciEpSetNrdy, + DwcXdciEp0ReceiveSetupPkt, + DwcXdciEp0ReceiveStatusPkt, + DwcXdciEp0SendStatusPkt, + DwcXdciEpTxData, + DwcXdciEpRxData, + DwcXdciEpCancelTransfer +}; + +const struct UsbDeviceCoreDriver *UsbDeviceGetCoreDriver(USB_CONTROLLER_ID= id) +{ + if (id >=3D USB_CORE_ID_MAX) + return NULL; + + return &CoreDriverTbl[id]; +} + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciU= tility.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciUti= lity.c new file mode 100644 index 0000000..2a756b9 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciUtility.= c @@ -0,0 +1,148 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "XdciUtility.h" + +VOID +PrintDeviceDescriptor ( + IN USB_DEVICE_DESCRIPTOR *DevDesc + ) +{ + DEBUG ((DEBUG_INFO, "--- Device Descriptor ---\n")); + DEBUG ((DEBUG_INFO, "Length : 0x%x\n", DevDesc->Length)); + DEBUG ((DEBUG_INFO, "DescriptorType : 0x%x\n", DevDesc->DescriptorTyp= e)); + DEBUG ((DEBUG_INFO, "BcdUSB : 0x%x\n", DevDesc->BcdUSB)); + DEBUG ((DEBUG_INFO, "DeviceClass : 0x%x\n", DevDesc->DeviceClass))= ; + DEBUG ((DEBUG_INFO, "DeviceSubClass : 0x%x\n", DevDesc->DeviceSubClas= s)); + DEBUG ((DEBUG_INFO, "DeviceProtocol : 0x%x\n", DevDesc->DeviceProtoco= l)); + DEBUG ((DEBUG_INFO, "MaxPacketSize0 : 0x%x\n", DevDesc->MaxPacketSize= 0)); + DEBUG ((DEBUG_INFO, "IdVendor : 0x%x\n", DevDesc->IdVendor)); + DEBUG ((DEBUG_INFO, "IdProduct : 0x%x\n", DevDesc->IdProduct)); + DEBUG ((DEBUG_INFO, "BcdDevice : 0x%x\n", DevDesc->BcdDevice)); + DEBUG ((DEBUG_INFO, "StrManufacturer : 0x%x\n", DevDesc->StrManufactur= er)); + DEBUG ((DEBUG_INFO, "StrProduct : 0x%x\n", DevDesc->StrProduct)); + DEBUG ((DEBUG_INFO, "StrSerialNumber : 0x%x\n", DevDesc->StrSerialNumb= er)); + DEBUG ((DEBUG_INFO, "NumConfigurations : 0x%x\n", DevDesc->NumConfigurat= ions)); + DEBUG ((DEBUG_INFO, "\n")); +} + +VOID +PrintConfigDescriptor ( + IN EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc + ) +{ + DEBUG ((DEBUG_INFO, "--- Configuration Descriptor ---\n")); + DEBUG ((DEBUG_INFO, "Length : 0x%x\n", ConfigDesc->Length)); + DEBUG ((DEBUG_INFO, "DescriptorType : 0x%x\n", ConfigDesc->Descripto= rType)); + DEBUG ((DEBUG_INFO, "TotalLength : 0x%x\n", ConfigDesc->TotalLeng= th)); + DEBUG ((DEBUG_INFO, "NumInterfaces : 0x%x\n", ConfigDesc->NumInterf= aces)); + DEBUG ((DEBUG_INFO, "ConfigurationValue : 0x%x\n", ConfigDesc->Configura= tionValue)); + DEBUG ((DEBUG_INFO, "Configuration : 0x%x\n", ConfigDesc->Configura= tion)); + DEBUG ((DEBUG_INFO, "Attributes : 0x%x\n", ConfigDesc->Attribute= s)); + DEBUG ((DEBUG_INFO, "MaxPower : 0x%x\n", ConfigDesc->MaxPower)= ); + DEBUG ((DEBUG_INFO, "\n")); +} + +VOID +PrintInterfaceDescriptor ( + IN EFI_USB_INTERFACE_DESCRIPTOR *IfDesc + ) +{ + DEBUG ((DEBUG_INFO, "--- Interface Descriptor ---\n")); + DEBUG ((DEBUG_INFO, "Length : 0x%x\n", IfDesc->Length)); + DEBUG ((DEBUG_INFO, "DescriptorType : 0x%x\n", IfDesc->DescriptorType= )); + DEBUG ((DEBUG_INFO, "InterfaceNumber : 0x%x\n", IfDesc->InterfaceNumbe= r)); + DEBUG ((DEBUG_INFO, "AlternateSetting : 0x%x\n", IfDesc->AlternateSetti= ng)); + DEBUG ((DEBUG_INFO, "NumEndpoints : 0x%x\n", IfDesc->NumEndpoints))= ; + DEBUG ((DEBUG_INFO, "InterfaceClass : 0x%x\n", IfDesc->InterfaceClass= )); + DEBUG ((DEBUG_INFO, "InterfaceSubClass : 0x%x\n", IfDesc->InterfaceSubCl= ass)); + DEBUG ((DEBUG_INFO, "InterfaceProtocol : 0x%x\n", IfDesc->InterfaceProto= col)); + DEBUG ((DEBUG_INFO, "Interface : 0x%x\n", IfDesc->Interface)); + DEBUG ((DEBUG_INFO, "\n")); +} + +VOID +PrintEpDescriptor ( + IN EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc + ) +{ + DEBUG ((DEBUG_INFO, "--- Endpoint Descriptor ---\n")); + DEBUG ((DEBUG_INFO, "Length : 0x%x\n", EpDesc->Length)); + DEBUG ((DEBUG_INFO, "DescriptorType : 0x%x\n", EpDesc->DescriptorType))= ; + DEBUG ((DEBUG_INFO, "EndpointAddress : 0x%x\n", EpDesc->EndpointAddress)= ); + DEBUG ((DEBUG_INFO, "Attributes : 0x%x\n", EpDesc->Attributes)); + DEBUG ((DEBUG_INFO, "MaxPacketSize : 0x%x\n", EpDesc->MaxPacketSize)); + DEBUG ((DEBUG_INFO, "Interval : 0x%x\n", EpDesc->Interval)); + DEBUG ((DEBUG_INFO, "\n")); +} + +VOID +PrintEpCompDescriptor ( + IN EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR *EpDesc + ) +{ + DEBUG ((DEBUG_INFO, "--- Endpoint Companion Descriptor ---\n")); + DEBUG ((DEBUG_INFO, "Length : 0x%x\n", EpDesc->Length)); + DEBUG ((DEBUG_INFO, "DescriptorType : 0x%x\n", EpDesc->DescriptorType)= ); + DEBUG ((DEBUG_INFO, "MaxBurst : 0x%x\n", EpDesc->MaxBurst)); + DEBUG ((DEBUG_INFO, "Attributes : 0x%x\n", EpDesc->Attributes)); + DEBUG ((DEBUG_INFO, "BytesPerInterval : 0x%x\n", EpDesc->BytesPerInterva= l)); + DEBUG ((DEBUG_INFO, "\n")); +} + +VOID +PrintStringDescriptor ( + IN USB_STRING_DESCRIPTOR *StrDesc + ) +{ + UINT16 StrLen =3D 0; + + if (StrDesc->Length > 2) { + StrLen =3D ((StrDesc->Length - 2) >> 1); + DEBUG ((DEBUG_INFO, "--- String Descriptor ---\n")); + DEBUG ((DEBUG_INFO, "Length : 0x%x\n", StrDesc->Length)); + DEBUG ((DEBUG_INFO, "DescriptorType : 0x%x\n", StrDesc->DescriptorType= )); + DEBUG ((DEBUG_INFO, "String : %s\n", StrDesc->LangID)); + } + DEBUG ((DEBUG_INFO, "\n")); +} + +VOID +PrintDeviceRequest ( + IN EFI_USB_DEVICE_REQUEST *DevReq + ) +{ + DEBUG ((DEBUG_INFO, "--- Device Request ---\n")); + DEBUG ((DEBUG_INFO, "RequestType : 0x%x\n", DevReq->RequestType)); + DEBUG ((DEBUG_INFO, "Request : 0x%x\n", DevReq->Request)); + DEBUG ((DEBUG_INFO, "Value : 0x%x\n", DevReq->Value)); + DEBUG ((DEBUG_INFO, "Index : 0x%x\n", DevReq->Index)); + DEBUG ((DEBUG_INFO, "Length : 0x%x\n", DevReq->Length)); + DEBUG ((DEBUG_INFO, "\n")); +} + +#ifdef SUPPORT_SUPER_SPEED +VOID +PrintBOSDescriptor ( + IN EFI_USB_BOS_DESCRIPTOR *BosDesc + ) +{ + DEBUG ((DEBUG_INFO, "--- BOS Descriptor ---\n")); + DEBUG ((DEBUG_INFO, "Length : 0x%x\n", BosDesc->Length)); + DEBUG ((DEBUG_INFO, "DescriptorType : 0x%x\n", BosDesc->DescriptorType= )); + DEBUG ((DEBUG_INFO, "TotalLength : 0x%x\n", BosDesc->TotalLength)); + DEBUG ((DEBUG_INFO, "NumDeviceCaps : 0x%x\n", BosDesc->NumDeviceCaps)= ); + DEBUG ((DEBUG_INFO, "\n")); +} +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciU= tility.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciUti= lity.h new file mode 100644 index 0000000..c243a5b --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciUtility.= h @@ -0,0 +1,62 @@ +/** @file + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef _XDCI_UTILITY_H_ +#define _XDCI_UTILITY_H_ + +#include + +VOID +PrintDeviceDescriptor ( + IN USB_DEVICE_DESCRIPTOR *DevDesc + ); + +VOID +PrintConfigDescriptor ( + IN EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc + ); + +VOID +PrintInterfaceDescriptor ( + IN EFI_USB_INTERFACE_DESCRIPTOR *IfDesc + ); + +VOID +PrintEpDescriptor ( + IN EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc + ); + +VOID +PrintEpCompDescriptor ( + IN EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR *EpDesc + ); + +VOID +PrintStringDescriptor ( + IN USB_STRING_DESCRIPTOR *StrDesc + ); + +VOID +PrintDeviceRequest ( + IN EFI_USB_DEVICE_REQUEST *DevReq + ); + +#ifdef SUPPORT_SUPER_SPEED +VOID +PrintBOSDescriptor ( + IN EFI_USB_BOS_DESCRIPTOR *BosDesc + ); +#endif + +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Include/Protocol/EfiUsbFnIo= .h b/Platform/BroxtonPlatformPkg/Common/Include/Protocol/EfiUsbFnIo.h new file mode 100644 index 0000000..7b1d4a9 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Include/Protocol/EfiUsbFnIo.h @@ -0,0 +1,430 @@ +/** @file + EFI USB function IO Protocol + This protocol supports Usb Function IO API. + Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef __EFI_USB_FUNC_IO_H__ +#define __EFI_USB_FUNC_IO_H__ + +#include + +#define EFI_USBFN_IO_PROTOCOL_REVISION 0x00010001 + +// +// {32D2963A-FE5D-4f30-B633-6E5DC55803CC} +// #define EFI_USBFN_IO_PROTOCOL_GUID {0x32d2963a, 0xfe5d, 0x4f30, 0xb6, = 0x33, 0x6e, 0x5d, 0xc5, 0x58, 0x3, 0xcc }; +// + +typedef struct _EFI_USBFN_IO_PROTOCOL EFI_USBFN_IO_PROTOCOL; + +// +// USB standard descriptors and reqeust +// +typedef USB_DEVICE_REQUEST EFI_USB_DEVICE_REQUEST; +typedef USB_DEVICE_DESCRIPTOR EFI_USB_DEVICE_DESCRIPTOR; +typedef USB_CONFIG_DESCRIPTOR EFI_USB_CONFIG_DESCRIPTOR; +typedef USB_INTERFACE_DESCRIPTOR EFI_USB_INTERFACE_DESCRIPTOR; +typedef USB_ENDPOINT_DESCRIPTOR EFI_USB_ENDPOINT_DESCRIPTOR; + +typedef enum _EFI_USBFN_PORT_TYPE { + EfiUsbUnknownPort =3D 0, + EfiUsbStandardDownstreamPort, + EfiUsbChargingDownstreamPort, + EfiUsbDedicatedChargingPort, + EfiUsbInvalidDedicatedChargingPort +} EFI_USBFN_PORT_TYPE; + +/** + USB_DEVICE_DESCRIPTOR, USB_CONFIG_DESCRIPTOR, USB_INTERFACE_DESCRIPTOR, a= nd + USB_ENDPOINT_DESCRIPTOR are already defined + in UEFI spec 2.3, as par USB 2.0 spec. +**/ + +typedef struct { + EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR **EndpointDescriptorTable; +} EFI_USB_INTERFACE_INFO; + +typedef struct { + EFI_USB_CONFIG_DESCRIPTOR *ConfigDescriptor; + EFI_USB_INTERFACE_INFO **InterfaceInfoTable; +} EFI_USB_CONFIG_INFO; + +typedef struct { + EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor; + EFI_USB_CONFIG_INFO **ConfigInfoTable; +} EFI_USB_DEVICE_INFO; + + +typedef enum _EFI_USB_ENDPOINT_TYPE { + UsbEndpointControl =3D 0x00, + UsbEndpointIsochronous =3D 0x01, + UsbEndpointBulk =3D 0x02, + UsbEndpointInterrupt =3D 0x03 +} EFI_USB_ENDPOINT_TYPE; + + +typedef enum _EFI_USBFN_DEVICE_INFO_ID { + EfiUsbDeviceInfoUnknown =3D 0, + EfiUsbDeviceInfoSerialNumber, + EfiUsbDeviceInfoManufacturerName, + EfiUsbDeviceInfoProductName +} EFI_USBFN_DEVICE_INFO_ID; + + +typedef enum _EFI_USBFN_ENDPOINT_DIRECTION { + EfiUsbEndpointDirectionHostOut =3D 0, + EfiUsbEndpointDirectionHostIn, + EfiUsbEndpointDirectionDeviceTx =3D EfiUsbEndpointDirectionHostIn, + EfiUsbEndpointDirectionDeviceRx =3D EfiUsbEndpointDirectionHostOut +} EFI_USBFN_ENDPOINT_DIRECTION; + + +typedef enum _EFI_USBFN_MESSAGE { + // + // Nothing + // + EfiUsbMsgNone =3D 0, + // + // SETUP packet is received, returned Buffer contains + // EFI_USB_DEVICE_REQUEST struct + // + EfiUsbMsgSetupPacket, + // + // Indicates that some of the requested data has been received from the + // host. It is the responsibility of the class driver to determine if it + // needs to wait for any remaining data. Returned Buffer contains + // EFI_USBFN_TRANSFER_RESULT struct containing endpoint number, transfer + // status and count of bytes received. + // + EfiUsbMsgEndpointStatusChangedRx, + // + // Indicates that some of the requested data has been transmitted to the + // host. It is the responsibility of the class driver to determine if an= y + // remaining data needs to be resent. Returned Buffer contains + // EFI_USBFN_TRANSFER_RESULT struct containing endpoint number, transfer + // status and count of bytes sent. + // + EfiUsbMsgEndpointStatusChangedTx, + // + // DETACH bus event signaled + // + EfiUsbMsgBusEventDetach, + // + // ATTACH bus event signaled + // + EfiUsbMsgBusEventAttach, + // + // RESET bus event signaled + // + EfiUsbMsgBusEventReset, + // + // SUSPEND bus event signaled + // + EfiUsbMsgBusEventSuspend, + // + // RESUME bus event signaled + // + EfiUsbMsgBusEventResume, + // + // Bus speed updated, returned buffer indicated bus speed using + // following enumeration named EFI_USB_BUS_SPEED + // + EfiUsbMsgBusEventSpeed +} EFI_USBFN_MESSAGE; + + +typedef enum _EFI_USBFN_TRANSFER_STATUS { + UsbTransferStatusUnknown =3D 0, + UsbTransferStatusComplete, + UsbTransferStatusAborted, + UsbTransferStatusActive, + UsbTransferStatusNone +} EFI_USBFN_TRANSFER_STATUS; + + +typedef struct _EFI_USBFN_TRANSFER_RESULT { + UINTN BytesTransferred; + EFI_USBFN_TRANSFER_STATUS TransferStatus; + UINT8 EndpointIndex; + EFI_USBFN_ENDPOINT_DIRECTION Direction; + VOID *Buffer; +} EFI_USBFN_TRANSFER_RESULT; + +typedef enum _EFI_USB_BUS_SPEED { + UsbBusSpeedUnknown =3D 0, + UsbBusSpeedLow, + UsbBusSpeedFull, + UsbBusSpeedHigh, + UsbBusSpeedSuper, + UsbBusSpeedMaximum =3D UsbBusSpeedSuper +} EFI_USB_BUS_SPEED; + +typedef union _EFI_USBFN_MESSAGE_PAYLOAD { + EFI_USB_DEVICE_REQUEST udr; + EFI_USBFN_TRANSFER_RESULT utr; + EFI_USB_BUS_SPEED ubs; +} EFI_USBFN_MESSAGE_PAYLOAD; + +typedef enum _EFI_USBFN_POLICY_TYPE { + EfiUsbPolicyUndefined =3D 0, + EfiUsbPolicyMaxTransactionSize, + EfiUsbPolicyZeroLengthTerminationSupport, + EfiUsbPolicyZeroLengthTermination +} EFI_USBFN_POLICY_TYPE; + + +/** + + Allocates transfer buffer of the specified size that satisfies + controller requirements. + + The AllocateTransferBuffer function allocates a memory region of Size byt= es and + returns the address of the allocated memory that satisfies underlying + controller requirements in the location referenced by Buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_ALLOCATE_TRANSFER_BUFFER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + + Deallocates the memory allocated for the transfer buffer by AllocateTran= sferBuffer function. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_FREE_TRANSFER_BUFFER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN VOID *Buffer + ); + +/** + Returns information about what type of device was attached. + +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_DETECT_PORT) ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT EFI_USBFN_PORT_TYPE *PortType + ); + +/** + Configure endpoints based on supplied device and configuration descripto= rs. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_CONFIGURE_ENABLE_ENDPOINTS) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USB_DEVICE_INFO *DeviceInfo + ); + + +/** + Returns the maximum packet size of the specified endpoint type for the s= upplied bus speed. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_GET_ENDPOINT_MAXPACKET_SIZE) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USB_ENDPOINT_TYPE EndpointType, + IN EFI_USB_BUS_SPEED BusSpeed, + OUT UINT16 *MaxPacketSize + ); + +/** + Returns the maximum supported transfer size. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_GET_MAXTRANSFER_SIZE) ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT UINTN *MaxTransferSize + ); + +/** + Returns device specific information based on the supplied identifier as = a + Unicode string. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_GET_DEVICE_INFO) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN EFI_USBFN_DEVICE_INFO_ID Id, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer OPTIONAL + ); + +/** + Returns vendor-id and product-id of the device. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_GET_VENDOR_ID_PRODUCT_ID) ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT UINT16 *Vid, + OUT UINT16 *Pid + ); + +/** + Aborts transfer on the specified endpoint. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_ABORT_TRANSFER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction + ); + +/** + Returns the stall state on the specified endpoint. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_GET_ENDPOINT_STALL_STATE) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT BOOLEAN *State + ); + +/** + Sets or clears the stall state on the specified endpoint. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_SET_ENDPOINT_STALL_STATE) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN BOOLEAN State + ); + + +/** + This function is called repeatedly to receive updates on USB bus states, + receive, transmit status changes on endpoints and setup packet on endpoi= nt 0. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_EVENTHANDLER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + OUT EFI_USBFN_MESSAGE *Message, + IN OUT UINTN *PayloadSize, + OUT EFI_USBFN_MESSAGE_PAYLOAD *Payload + ); + +/** + Primary function to handle transfer in either direction based on specifi= ed + direction and on the specified endpoint. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USBFN_IO_TRANSFER) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN OUT UINTN *BufferSize, + IN OUT VOID *Buffer + ); + +/** + This function supplies power to the USB controller if needed, + initialize hardware and internal data structures, and then return. + + The port must not be activated by this function. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_START_CONTROLLER) ( + IN EFI_USBFN_IO_PROTOCOL *This + ); + +/** + This function disables the hardware device by resetting the run/stop bit= and + power off the USB controller if needed. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_STOP_CONTROLLER) ( + IN EFI_USBFN_IO_PROTOCOL *This + ); + +/** + This function sets the configuration policy for the specified non-contro= l endpoint. + + Refer to the description for calling restrictions. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_SET_ENDPOINT_POLICY) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN EFI_USBFN_POLICY_TYPE PolicyType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + This function retrieves the configuration policy for the specified non-c= ontrol endpoint. + + There are no associated calling restrictions for this function. +**/ +typedef +EFI_STATUS +(EFIAPI * EFI_USBFN_IO_GET_ENDPOINT_POLICY) ( + IN EFI_USBFN_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + IN EFI_USBFN_ENDPOINT_DIRECTION Direction, + IN EFI_USBFN_POLICY_TYPE PolicyType, + IN OUT UINTN *BufferSize, + IN OUT VOID *Buffer + ); + + +struct _EFI_USBFN_IO_PROTOCOL { + UINT32 Revision; + EFI_USBFN_IO_DETECT_PORT DetectPort; + EFI_USBFN_IO_CONFIGURE_ENABLE_ENDPOINTS ConfigureEnableEndpoints; + EFI_USBFN_IO_GET_ENDPOINT_MAXPACKET_SIZE GetEndpointMaxPacketSize; + EFI_USBFN_IO_GET_DEVICE_INFO GetDeviceInfo; + EFI_USBFN_IO_GET_VENDOR_ID_PRODUCT_ID GetVendorIdProductId; + EFI_USBFN_IO_ABORT_TRANSFER AbortTransfer; + EFI_USBFN_IO_GET_ENDPOINT_STALL_STATE GetEndpointStallState; + EFI_USBFN_IO_SET_ENDPOINT_STALL_STATE SetEndpointStallState; + EFI_USBFN_IO_EVENTHANDLER EventHandler; + EFI_USBFN_IO_TRANSFER Transfer; + EFI_USBFN_IO_GET_MAXTRANSFER_SIZE GetMaxTransferSize; + EFI_USBFN_IO_ALLOCATE_TRANSFER_BUFFER AllocateTransferBuffer; + EFI_USBFN_IO_FREE_TRANSFER_BUFFER FreeTransferBuffer; + // + // Valid for version EFI_USBFN_IO_PROTOCOL_REVISION2 and above + // + EFI_USBFN_IO_START_CONTROLLER StartController; + EFI_USBFN_IO_STOP_CONTROLLER StopController; + EFI_USBFN_IO_SET_ENDPOINT_POLICY SetEndpointPolicy; + EFI_USBFN_IO_GET_ENDPOINT_POLICY GetEndpointPolicy; +}; + + +extern EFI_GUID gEfiUsbFnIoProtocolGuid; +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Include/Protocol/UsbDeviceM= odeProtocol.h b/Platform/BroxtonPlatformPkg/Common/Include/Protocol/UsbDevi= ceModeProtocol.h new file mode 100644 index 0000000..bd8d85f --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Include/Protocol/UsbDeviceModeProt= ocol.h @@ -0,0 +1,104 @@ +/** @file + Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + + +#ifndef _USB_DEVICE_MODE_PROTOCOL_H_ +#define _USB_DEVICE_MODE_PROTOCOL_H_ + +#include + +/// +/// UsbDeviceMode Protocol GUID. +/// +#define EFI_USB_DEVICE_MODE_PROTOCOL_GUID \ + {0xC9923F7E, 0x1746, 0x4802, { 0x86, 0x2e, 0x1, 0x1c, 0x2c, 0x2d, 0x9d, = 0x86 } } + +typedef struct _EFI_USB_DEVICE_MODE_PROTOCOL EFI_USB_DEVICE_MODE_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_DEVICE_MODE_INIT_XDCI) ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_DEVICE_MODE_CONNECT) ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_DEVICE_MODE_DISCONNECT) ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_DEVICE_EP_TX_DATA) ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This, + IN USB_DEVICE_IO_REQ *IoRequest + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_DEVICE_EP_RX_DATA) ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This, + IN USB_DEVICE_IO_REQ *IoRequest + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_DEVICE_MODE_BIND) ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This, + IN USB_DEVICE_OBJ *UsbdDevObj + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_DEVICE_MODE_UNBIND) ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_DEVICE_MODE_STOP) ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_DEVICE_MODE_RUN) ( + IN EFI_USB_DEVICE_MODE_PROTOCOL *This, + IN UINT32 TimeoutMs + ); + +/// +/// Usb Device Mode Protocol Structure. +/// +struct _EFI_USB_DEVICE_MODE_PROTOCOL { + EFI_USB_DEVICE_MODE_INIT_XDCI InitXdci; + EFI_USB_DEVICE_MODE_CONNECT Connect; + EFI_USB_DEVICE_MODE_DISCONNECT DisConnect; + EFI_USB_DEVICE_EP_TX_DATA EpTxData; + EFI_USB_DEVICE_EP_RX_DATA EpRxData; + EFI_USB_DEVICE_MODE_BIND Bind; + EFI_USB_DEVICE_MODE_UNBIND UnBind; + EFI_USB_DEVICE_MODE_RUN Run; + EFI_USB_DEVICE_MODE_STOP Stop; +}; + +extern EFI_GUID gEfiUsbDeviceModeProtocolGuid; + +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicDummy.c= b/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicDummy.c new file mode 100644 index 0000000..570bc21 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicDummy.c @@ -0,0 +1,142 @@ +/** @file + Dxe library for accessing dummy PMIC registers. + + Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + + +#include +#include +#include +#include "PmicPrivate.h" + +/** + Reads an 8-bit PMIC register. + + Reads the 8-bit PMIC register specified by Register. + The 8-bit read value is returned. + + @param[in] BaseAddress - IPC operation address for target PMIC devi= ce. + @param[in] Register - The PMIC register to read. + + @retval 0 - Function not supported yet. +**/ +UINT8 +EFIAPI +DmPmicRead8 ( + IN UINT8 BaseAddress, + IN UINT8 Register + ) +{ + return 0x0; +} + +/** + Writes an 8-bit PMIC register with a 8-bit value. + + Writes the 8-bit PMIC register specified by Register with the value spec= ified + by Value and return the operation status. + + @param[in] BaseAddress - IPC operation address for target PMIC devi= ce. + @param[in] Register - The PMIC register to write. + @param[in] Value - The value to write to the PMIC register. + + @retval EFI_SUCCESS - Function not supported yet. +**/ +EFI_STATUS +EFIAPI +DmPmicWrite8 ( + IN UINT8 BaseAddress, + IN UINT8 Register, + IN UINT8 Value + ) +{ + return EFI_SUCCESS; +} + +/** + AC/DC Adapter Detection Status + + @retval TRUE - Connected +**/ +BOOLEAN +EFIAPI +DmPmicIsACOn ( + VOID + ) +{ + return TRUE; +} + +/** + Probe to find the correct PMIC object. + + After probling, g_pmic_obj points to correct PMIC object + This routine is invoked when library is loaded . + + @retval TRUE - Always return true to indicate dummy PMIC = existed. +**/ +BOOLEAN +EFIAPI +DmPmicProbe ( + VOID + ) +{ + DEBUG ((DEBUG_ERROR, "Dummy PMIC detected\n")); + return TRUE; +} + +struct PmicObject DmObj =3D { + PMIC_I2C_BUSNO, + PMIC_PAGE_0_I2C_ADDR, + PMIC_PAGE_0_I2C_ADDR, + PMIC_TYPE_DUMMY, + DmPmicRead8, + DmPmicWrite8, + + DmPmicProbe, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + =20 + // + //PUPDR interfaces + // + NULL, + NULL, + NULL, + NULL, + NULL, + DmPmicIsACOn, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + diff --git a/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicLibNull= .c b/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicLibNull.c new file mode 100644 index 0000000..b0abe48 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicLibNull.c @@ -0,0 +1,658 @@ +/** @file + Dxe Library for PMIC public API. + + Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + + +#include +#include +#include "PmicPrivate.h" + + +struct PmicObject *gPmicObj =3D NULL; + +extern struct PmicObject DmObj; + + +struct PmicObject *gPmicSupportList[] =3D { + &DmObj, //dummy +}; + + +PMIC_TYPE gPmicType =3D PMIC_TYPE_NONE; //global flag to record current = probed PMIC type. We could use it to avoid probe HW every time in API. + +/** + Reads an 8-bit PMIC register. + + Reads the 8-bit PMIC register specified by Register. + The 8-bit read value is returned. + + @param[in] BaseAddress - IPC operation address for target PMIC devi= ce. + @param[in] Register - The PMIC register to read. + + @retval UINT8 - The value read. +**/ +UINT8 +EFIAPI +PmicRead8 ( + IN UINT8 BaseAddress, + IN UINT8 Register + ) +{ + RETURN_IF_POINTER_NULL(PmicRead8, 0xff) + return gPmicObj->PmicRead8(BaseAddress, Register); +} + +/** + Writes an 8-bit PMIC register with a 8-bit value. + + Writes the 8-bit PMIC register specified by Register with the value spec= ified + by Value and return the operation status. + + @param[in] BaseAddress - IPC operation address for target PMIC devi= ce. + @param[in] Register - The PMIC register to write. + @param[in] Value - The value to write to the PMIC register. + + @retval EFI_SUCCESS - Write bytes to PMIC device successfully + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicWrite8 ( + IN UINT8 BaseAddress, + IN UINT8 Register, + IN UINT8 Value + ) +{ + RETURN_IF_POINTER_NULL(PmicWrite8, EFI_UNSUPPORTED) + return gPmicObj->PmicWrite8(BaseAddress, Register, Value); +} + +/** + Get previous shutdown root cause. + + @param[in, out] ShutdownCause - The data to store shutdown root cause. + + @retval EFI_SUCCESS - Get shutdown root cause successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicGetShutdownCause ( + IN OUT UINT32 *ShutdownCause + ) +{ + RETURN_IF_POINTER_NULL(PmicGetShutdownCause, EFI_UNSUPPORTED) + return gPmicObj->PmicGetShutdownCause(ShutdownCause); +} + +/** + Get previous reset root cause + + @param[in, out] ResetSrc - The data to store reset root cause + + @retval EFI_SUCCESS - Get reset root cause successfully. + @retval EFI_INVALID_PARAMETER - ResetSrc is NULL. +**/ +EFI_STATUS +EFIAPI +PmicGetResetSrc (UINT32 *ResetSrc) +{ + RETURN_IF_POINTER_NULL(PmicGetResetSrc, EFI_UNSUPPORTED) + return gPmicObj->PmicGetResetSrc(ResetSrc); +} + +/** + Get the cause of system wake event. + + @param[in, out] WakeCause - The data to store the cause of wake event= . + + @retval EFI_SUCCESS - Get wake cause successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicGetWakeCause ( + IN OUT UINT32 *WakeCause + ) +{ + RETURN_IF_POINTER_NULL(PmicGetWakeCause, EFI_UNSUPPORTED) + return gPmicObj->PmicGetWakeCause(WakeCause); +} + +/** + Get power source detection result. + + @param[in, out] PowerSrcIrq - The data to the cause of wake event. + + @retval EFI_SUCCESS - Get power source successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicGetPwrSrcIrq ( + IN OUT UINT32 *PowerSrcIrq + ) +{ + RETURN_IF_POINTER_NULL(PmicGetPwrSrcIrq, EFI_UNSUPPORTED) + return gPmicObj->PmicGetPwrSrcIrq(PowerSrcIrq); +} + +/** + Battery Detection Status + + @retval TRUE - Connected + @retval FALSE - Disconnected +**/ +BOOLEAN +EFIAPI +PmicIsBatOn ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicIsBatOn, TRUE) + return gPmicObj->PmicIsBatOn(); +} + +/** + AC/DC Adapter Detection Status + + @retval TRUE - Connected + @retval FALSE - Disconnected +**/ +BOOLEAN +EFIAPI +PmicIsACOn ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicIsACOn, TRUE) + return gPmicObj->PmicIsACOn(); +} + +/** + VBUS Detection Status + + It can be used to detect whether USB charger is connected. + + @retval TRUE - Connected + @retval FALSE - Disconnected +**/ +BOOLEAN +EFIAPI +PmicVbusStatus ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicVbusStatus, TRUE) + return gPmicObj->PmicVbusStatus(); +} + +/** + USB ID Detection Status + + @retval UINT8 - Value depends on each PMIC operation. +**/ +UINT8 +EFIAPI +PmicUSBIDStatus ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicUSBIDStatus, TRUE) + return gPmicObj->PmicUSBIDStatus(); +} + +/** + Clear previous shutdown root cause. + + @retval EFI_SUCCESS - Clear shutdown root cause successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicClearShutdownCause ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicClearShutdownCause, EFI_UNSUPPORTED) + + return gPmicObj->PmicClearShutdownCause(); +} + +/** + Clear the cause of system wake event. + + @retval EFI_SUCCESS - Clear wake cause successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicClearWakeCause ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicClearWakeCause, EFI_UNSUPPORTED) + return gPmicObj->PmicClearWakeCause(); +} + +/** + Clear the cause of system reset. + + @retval EFI_SUCCESS - Clear reset cause successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicClearResetSrc ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicClearResetSrc, EFI_UNSUPPORTED) + return gPmicObj->PmicClearResetSrc(); +} + +/** + Initialize PMIC thermal detection capability. + + @retval EFI_SUCCESS - Initialize thermal detection successfully= . + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicThermInit ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicThermInit, EFI_UNSUPPORTED) + return gPmicObj->PmicThermInit(); +} + +/** + Initialize PMIC GPIO pin. + + Initialize PMIC GPIO pin in order to get boardid/memcfgid/.. etc later + + @param[in] PlatformInfo - Platform information with GPIO setting. + + @retval EFI_SUCCESS - Initialize GPIO pin successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicGpioInit ( + IN VOID *PlatformInfo + ) +{ + RETURN_IF_POINTER_NULL(PmicGpioInit, EFI_UNSUPPORTED) + return gPmicObj->PmicGpioInit(PlatformInfo); +} + +/** + Initializes PMIC device. + + @retval EFI_SUCCESS - Initialize PMIC successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicIntrInit ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicIntrInit, EFI_UNSUPPORTED) + return gPmicObj->PmicIntrInit(); +} + +/** + Initializes Burst Control Unit (BCU) hardware. + + The BCU has several different knobs (input stimuli configuration, interr= upts, + and output actions) that allow the Software and Firmware to change the B= CU response + behavior once these events occur. These BCU control knobs allow for a ch= ange in the + BCU behavior in responding to these triggers and can be completely custo= mized as + necessary by the specific system implementation. + + @retval EFI_SUCCESS - Initializes BCU hardware successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicBcuInit ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicBcuInit, EFI_UNSUPPORTED) + return gPmicObj->PmicBcuInit(); +} + +/** + Initializes other miscellaneous functions on PMIC device. + + @retval EFI_SUCCESS - Initializes miscellaneous functions succe= ssfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicMiscInit ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicMiscInit, EFI_UNSUPPORTED) + return gPmicObj->PmicMiscInit (); +} + +/** + Turn on or off VBUS for OTG + + @param[in] Enable - TRUE : turn on VBUS + FALSE: turn off VBUS + + @retval EFI_SUCCESS - Turn on/off VBUS successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicVbusControl ( + IN BOOLEAN Enable + ) +{ + RETURN_IF_POINTER_NULL(PmicVbusControl, EFI_UNSUPPORTED) + return gPmicObj->PmicVbusControl(Enable); +} + +/** + Turn on or off 5V VBUS for USB2/3 HOST + + @param[in] Enable - TRUE : turn on V5P0S + FALSE: turn off V5P0S + + @retval EFI_SUCCESS - Turn on/off V5P0S successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicVhostControl ( + IN BOOLEAN Enable + ) +{ + RETURN_IF_POINTER_NULL(PmicVhostControl, EFI_UNSUPPORTED) + return gPmicObj->PmicVhostControl(Enable); +} + +/** + Get PMIC Vendor ID and Device ID + + @param[in, out] VenId - Vendor ID + @param[in, out] DevId - Device ID + + @retval EFI_SUCCESS - Get Vendor ID and Device ID successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicGetDevID ( + IN OUT UINT8 *VenId, + IN OUT UINT8 *DevId + ) +{ + RETURN_IF_POINTER_NULL(PmicGetDevID, EFI_UNSUPPORTED) + return gPmicObj->PmicGetDevID(VenId, DevId); +} + +/** + This procedure will get PMIC Stepping + + @retval PMIC Stepping +**/ +UINT8 +EFIAPI +PmicStepping ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicStepping, 0xff); + + return gPmicObj->PmicStepping(); +} + +/** + Get PMIC device instance + + @retval PMIC_TYPE - Device type is defined in PMIC_TYPE. +**/ +PMIC_TYPE +EFIAPI +PmicGetDeviceType ( + VOID + ) +{ + return gPmicObj->PmicType; +} + +/** + Get battery voltage. + + @retval UINT16 - ADC result for battery voltage. +**/ +UINT16 +EFIAPI +PmicGetVBAT ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicGetVBAT, 0xff) + return gPmicObj->PmicGetVBAT(); +} + +/** + Get battery capacity. + + @retval UINT16 - Remaining percentage of battery capacity. +**/ +UINT16 +EFIAPI +PmicGetBatteryCap ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicGetBatteryCap, 0xff) + return gPmicObj->PmicGetBatteryCap(); +} + +/** + Get power button status + + @retval TRUE - Power button pressed. + @retval FALSE - Power button released. +**/ +BOOLEAN +EFIAPI +PmicIsPwrBtnPressed ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicIsPwrBtnPressed, TRUE) + + return gPmicObj->PmicIsPwrBtnPressed(); +} + +/** + Disable the capability to shutdown platform using power button. + + @param[out] ButtonHoldTime - If the power button is disabled successfu= lly, + this contains the time in seconds need to= hold power button to shutdown platform. + + @retval EFI_SUCCESS - Succeed to disable power button + @retval Others - Failed to disable power button +**/ +EFI_STATUS +EFIAPI +PmicDisablePowerButton ( + OUT UINT8 *ButtonHoldTime + ) +{ + RETURN_IF_POINTER_NULL(PmicDisablePowerButton, EFI_UNSUPPORTED) + return gPmicObj->PmicDisablePowerButton(ButtonHoldTime); +} + +/** + Enable the capability to shutdown platform using power button. + + @param[in] ButtonHoldTime - Time in seconds to shut down the platform= if power button is enabled and hold + + @retval EFI_SUCCESS - Succeed to enable power button + @retval Others - Filed to enable power button +**/ +EFI_STATUS +EFIAPI +PmicEnablePowerButton ( + IN UINT8 ButtonHoldTime + ) +{ + RETURN_IF_POINTER_NULL(PmicEnablePowerButton, EFI_UNSUPPORTED) + return gPmicObj->PmicEnablePowerButton(ButtonHoldTime); +} + +/** + Set VDDQ to 1.35V for DDR3L + + @retval EFI_SUCCESS - Succeed to Set VDDQ + @retval Others - Filed to Set VDDQ +**/ +EFI_STATUS +EFIAPI +PmicSetVDDQ ( + VOID + ) +{ + RETURN_IF_POINTER_NULL(PmicSetVDDQ, EFI_UNSUPPORTED) + return gPmicObj->PmicSetVDDQ(); +} + +/** + Probe to find the correct PMIC object. + + After probling, g_pmic_obj points to correct PMIC object + This routine is invoked when library is loaded . + + @retval TRUE - There is one PMIC object found. + @retval FALSE - No PMIC object found. +**/ +BOOLEAN +EFIAPI +PmicProbe ( + VOID + ) +{ + gPmicObj =3D &DmObj; + return FALSE; +} + +/** + Read charger's register provided by PMIC. + + @param[in] Offset - The charger's register to read. + @param[out] Value - The value read. + + @retval EFI_SUCCESS - Read charger's register successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicChargerRead ( + IN UINT8 Offset, + OUT UINT8 *Value + ) +{ + RETURN_IF_POINTER_NULL(PmicChargerRead, EFI_UNSUPPORTED) + return gPmicObj->PmicChargerRead(Offset, Value); +} + +/** + Write charger's register provided by PMIC. + + @param[in] Offset - The charger's register to write. + @param[in] Value - The value written. + + @retval EFI_SUCCESS - Write charger's register successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicChargerWrite ( + IN UINT8 Offset, + IN UINT8 Value + ) +{ + RETURN_IF_POINTER_NULL(PmicChargerWrite, EFI_UNSUPPORTED) + return gPmicObj->PmicChargerWrite(Offset, Value); +} + +/** + Detect charger type and charger presence. + + @param[out] ChargerPresent - TRUE : Charger present. + FALSE: Charger not present. + @param[out] ChargerType - Charger type - SDP/DCP/CDP... etc. + + @retval EFI_SUCCESS - Detect charger type and charger presence = successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicDetectCharger ( + OUT BOOLEAN *ChargerPresent, + OUT UINT8 *ChargerType + ) +{ + RETURN_IF_POINTER_NULL(PmicDetectCharger, EFI_UNSUPPORTED) + return gPmicObj->PmicDetectCharger(ChargerPresent, ChargerType); +} + +/** + Controls external USB PHY reset + + @param[in] Enable - TRUE : OUTOFRESET - external PHY is out o= f reset + FALSE: INRESET - external PHY is in reset + + @retval EFI_SUCCESS - Controls external USB PHY successfully. + @retval Others - Status depends on each PMIC operation. +**/ +EFI_STATUS +EFIAPI +PmicUSBSwitchControl ( + IN BOOLEAN Enable + ) +{ + RETURN_IF_POINTER_NULL(PmicUSBSwitchControl, EFI_UNSUPPORTED) + return gPmicObj->PmicUSBSwitchControl(Enable); +} + +/** + Pmic library constructor + + PMIC type is probed in this function. It is invoked every time Pmiclib i= s loaded. + + @retval EFI_SUCCESS - Construct PMIC instance successfully. +**/ +RETURN_STATUS +EFIAPI +PmicLibConstructor ( + VOID + ) +{ + PmicProbe(); + return EFI_SUCCESS; +} + diff --git a/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicLibNull= .inf b/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicLibNull.inf new file mode 100644 index 0000000..35ceb79 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicLibNull.inf @@ -0,0 +1,44 @@ +## @file +# Dxe Library for accessing PMIC registers. +# +# +# Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e 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 IM= PLIED. +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PmicLibNull + FILE_GUID =3D 90c0faf8-cb8b-4726-a69c-c38a5b110c30 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D PmicLib + CONSTRUCTOR =3D PmicLibConstructor +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC +# + +[Sources.common] + PmicLibNull.c + PmicDummy.c + +[Packages] + MdePkg/MdePkg.dec + BroxtonPlatformPkg/PlatformPkg.dec + +[LibraryClasses] +#Althogh PMIClib does not use gBS(provided by UefiBootServicesTableLib), +#but libconstructor use i2c routine which uses gBS. +#UefiBootServicesTableLib is a must here. + UefiBootServicesTableLib + DebugLib diff --git a/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicPrivate= .h b/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicPrivate.h new file mode 100644 index 0000000..c173b38 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Library/PmicLib/PmicPrivate.h @@ -0,0 +1,82 @@ +/** @file + Private Header file for PMIC Dxe Driver + + Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + + + +#ifndef _PMIC_REG_PV_H_ +#define _PMIC_REG_PV_H_ + +#include +#include +#include + +/// +/// PMIC device object +/// +struct PmicObject { + UINT8 I2cbus; + UINT8 I2cSlaveAddr0; ///< page0 + UINT8 I2cSlaveAddr1; ///< page1 + PMIC_TYPE PmicType; + UINT8 (EFIAPI* PmicRead8) (IN UINT8 BaseAddress, IN UI= NT8 Register); + EFI_STATUS (EFIAPI* PmicWrite8) (IN UINT8 BaseAddress, IN UI= NT8 Register, IN UINT8 Value); + + BOOLEAN (EFIAPI* PmicProbe) (VOID); + EFI_STATUS (EFIAPI* PmicGetDevID) (IN OUT UINT8 *VenId, IN OUT= UINT8 *DevId); + UINT8 (EFIAPI* PmicStepping) (VOID); + EFI_STATUS (EFIAPI* PmicThermInit) (VOID); + EFI_STATUS (EFIAPI* PmicGpioInit) (IN VOID *PlatformInfo); + EFI_STATUS (EFIAPI* PmicIntrInit) (VOID); + EFI_STATUS (EFIAPI* PmicBcuInit) (VOID); + EFI_STATUS (EFIAPI* PmicMiscInit) (VOID); + EFI_STATUS (EFIAPI* PmicVbusControl) (IN BOOLEAN Enable); + EFI_STATUS (EFIAPI* PmicVhostControl) (IN BOOLEAN Enable); + EFI_STATUS (EFIAPI* PmicBatchRegisterInit) (IN RegInit_st *RegInit, IN = UINT32 length); + + /// + /// PUPDR interfaces + /// + EFI_STATUS (EFIAPI* PmicGetWakeCause) (IN OUT UINT32 *WakeCause); + EFI_STATUS (EFIAPI* PmicGetShutdownCause) (IN OUT UINT32 *ShutdownCaus= e); + EFI_STATUS (EFIAPI* PmicGetResetSrc) (IN OUT UINT32 *ResetSrc); + EFI_STATUS (EFIAPI* PmicGetPwrSrcIrq) (IN OUT UINT32 *PowerSrcIrq)= ; + BOOLEAN (EFIAPI* PmicIsBatOn) (VOID); + BOOLEAN (EFIAPI* PmicIsACOn) (VOID); + BOOLEAN (EFIAPI* PmicVbusStatus) (VOID); + EFI_STATUS (EFIAPI* PmicClearShutdownCause) (VOID); + EFI_STATUS (EFIAPI* PmicClearWakeCause) (VOID); + EFI_STATUS (EFIAPI* PmicClearResetSrc) (VOID); + UINT16 (EFIAPI* PmicGetVBAT) (VOID); + BOOLEAN (EFIAPI* PmicIsPwrBtnPressed) (VOID); + EFI_STATUS (EFIAPI* PmicDisablePowerButton) (OUT UINT8 *ButtonHoldTime); + EFI_STATUS (EFIAPI* PmicEnablePowerButton) (IN UINT8 ButtonHoldTime); + UINT16 (EFIAPI* PmicGetBatteryCap) (VOID); + EFI_STATUS (EFIAPI* PmicSetVDDQ) (VOID); + EFI_STATUS (EFIAPI* PmicChargerRead) (IN UINT8 Offset, OUT UINT8 = *Value); + EFI_STATUS (EFIAPI* PmicChargerWrite) (IN UINT8 Offset, IN UINT8 V= alue); + EFI_STATUS (EFIAPI* PmicDetectCharger) (OUT BOOLEAN *ChargerPresent= , OUT UINT8 *ChargerType); + EFI_STATUS (EFIAPI* PmicUSBSwitchControl) (IN BOOLEAN Enable); + UINT8 (EFIAPI* PmicUSBIDStatus) (VOID); +}; + +#define RETURN_IF_POINTER_NULL(method, value) { if ((NULL =3D=3D gPmicObj= ) || (NULL =3D=3D gPmicObj->method)) \ + {\ + DEBUG ((DEBUG_ERROR, "n= ull function pointer\n")); \ + return value; \ + }\ + } + +#endif + diff --git a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSe= tupDxe/SouthClusterConfig.vfi b/Platform/BroxtonPlatformPkg/Common/Platform= Settings/PlatformSetupDxe/SouthClusterConfig.vfi index 84ae466..411006b 100644 --- a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/= SouthClusterConfig.vfi +++ b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/= SouthClusterConfig.vfi @@ -1,7 +1,7 @@ // /** @file // South Cluster Setup formset. // -// Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.
+// Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
// // This program and the accompanying materials // are licensed and made available under the terms and conditions of the = BSD License @@ -2416,8 +2416,8 @@ form formid =3D USB_OPTIONS_FORM_ID, oneof varid =3D Setup.ScUsbOtg, prompt =3D STRING_TOKEN(STR_USB_XDCI_PROMPT), help =3D STRING_TOKEN(STR_USB_XDCI_HELP), - option text =3D STRING_TOKEN(STR_DISABLE), value =3D 0, flags =3D DEFA= ULT | MANUFACTURING | RESET_REQUIRED; - option text =3D STRING_TOKEN(STR_PCI_MODE_STRING), value =3D 1, flags = =3D RESET_REQUIRED; + option text =3D STRING_TOKEN(STR_DISABLE), value =3D 0, flags =3D RESE= T_REQUIRED; + option text =3D STRING_TOKEN(STR_PCI_MODE_STRING), value =3D 1, flags = =3D DEFAULT | MANUFACTURING | RESET_REQUIRED; // option text =3D STRING_TOKEN(STR_ACPI_MODE_STRING), value =3D 2, flags= =3D RESET_REQUIRED; endoneof; =20 diff --git a/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc b/Platf= orm/BroxtonPlatformPkg/PlatformDsc/Components.dsc index 53658cf..da61f84 100644 --- a/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc +++ b/Platform/BroxtonPlatformPkg/PlatformDsc/Components.dsc @@ -455,6 +455,8 @@ # PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf =20 + $(PLATFORM_PACKAGE_COMMON)/Features/UsbDeviceDxe/UsbDeviceDxe.inf + =20 # # USB TypeC # diff --git a/Platform/BroxtonPlatformPkg/PlatformDsc/LibraryClasses.dsc b/P= latform/BroxtonPlatformPkg/PlatformDsc/LibraryClasses.dsc index c7e8d76..9af21aa 100644 --- a/Platform/BroxtonPlatformPkg/PlatformDsc/LibraryClasses.dsc +++ b/Platform/BroxtonPlatformPkg/PlatformDsc/LibraryClasses.dsc @@ -1,7 +1,7 @@ ## @file # Library classes Description. # -# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# Copyright (c) 2017, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions of the B= SD License @@ -242,6 +242,8 @@ =20 BasePlatformCmosLib|$(PLATFORM_PACKAGE_COMMON)/Library/PlatformCmosLib/= PlatformCmosLib.inf =20 + PmicLib|$(PLATFORM_PACKAGE_COMMON)/Library/PmicLib/PmicLibNull.inf + # # Reference code Libraries # diff --git a/Platform/BroxtonPlatformPkg/PlatformPkg.fdf b/Platform/Broxton= PlatformPkg/PlatformPkg.fdf index 0d9a087..e190dca 100644 --- a/Platform/BroxtonPlatformPkg/PlatformPkg.fdf +++ b/Platform/BroxtonPlatformPkg/PlatformPkg.fdf @@ -705,6 +705,8 @@ APRIORI DXE { SECTION PE32 =3D ShellBinPkg/UefiShell/$(IA32_X64_LC)/Shell.efi } =20 + INF $(PLATFORM_PACKAGE_COMMON)/Features/UsbDeviceDxe/UsbDeviceDxe.inf =20 + # # USB TypeC # diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/Re= gsUsb.h b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/RegsU= sb.h index eeb03e2..bc55746 100644 --- a/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/RegsUsb.h +++ b/Silicon/BroxtonSoC/BroxtonSiPkg/SouthCluster/Include/ScRegs/RegsUsb.h @@ -17,7 +17,7 @@ - Registers / bits of new devices introduced in a SC generation will be = just named as "_SC_" without inserted. =20 - Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License @@ -563,6 +563,14 @@ #define B_XDCI_POW_PG_CONF_D3HEN BIT18 ///< D3-Hot Enable #define B_XDCI_POW_PG_CONF_DEVIDLEN BIT17 ///< DEVIDLE Enable =20 + +#define R_OTG_BAR0 0x10 ///< BAR 0 +#define B_OTG_BAR0_BA 0xFFE00000 ///< Base Address +#define V_OTG_BAR0_SIZE 0x200000 +#define N_OTG_BAR0_ALIGNMENT 21 +#define B_OTG_BAR0_PREF BIT3 ///< Prefetchable +#define B_OTG_BAR0_ADDRNG (BIT2 | BIT1) ///< Address Range +#define B_OTG_BAR0_SPTYP BIT0 ///< Space Type (Memory) #define R_OTG_GEN_INPUT_REGRW 0xC0 #define B_OTG_GEN_INPUT_REGRW_CPSU3 (BIT11 | BIT10) ///< Current Power= State u3pmu #define B_OTG_GEN_INPUT_REGRW_CPSU2 (BIT9 | BIT8) ///< Current Power S= tate u2pmu --=20 2.10.1.windows.1