diff options
author | Guo Mang <mang.guo@intel.com> | 2017-01-17 16:07:34 +0800 |
---|---|---|
committer | Guo Mang <mang.guo@intel.com> | 2017-05-09 13:03:08 +0800 |
commit | 90bcd27ee4f7596ad0d2c02e343e4aaa7ad89456 (patch) | |
tree | a810594a3955efd49a32b12c10aa23b288da3bf2 /Platform/BroxtonPlatformPkg/Common | |
parent | 319794588036f8a0f0d9144a2f9ed917e114f7d3 (diff) | |
download | edk2-platforms-90bcd27ee4f7596ad0d2c02e343e4aaa7ad89456.tar.xz |
Add USB peripheral mode
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Guo Mang <mang.guo@intel.com>
Reviewed-by: David Wei <david.wei@intel.com>
Diffstat (limited to 'Platform/BroxtonPlatformPkg/Common')
26 files changed, 12959 insertions, 3 deletions
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/ComponentName.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/ComponentName.c new file mode 100644 index 0000000000..94958060e7 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/ComponentName.c @@ -0,0 +1,305 @@ +/** @file
+ Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+
+
+/**
+ 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 of 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 specified
+ 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_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller 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 specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @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 specified by
+ This and the language specified by Language 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 support
+ 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 controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified 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 specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ 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 returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ 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 string
+ array indicating the language. This is the
+ language of the driver name that the caller 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 specified 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 and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name 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 valid
+ 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 currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbDeviceDxeGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL mUsbDeviceDxeComponentName = {
+ UsbDeviceDxeGetDriverName,
+ UsbDeviceDxeGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL mUsbDeviceDxeComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) UsbDeviceDxeGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) UsbDeviceDxeGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUsbDeviceDxeDriverNameTable[] = {
+ { "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 of 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 specified
+ 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_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller 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 specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @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 specified by
+ This and the language specified by Language 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 support
+ 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 == &mUsbDeviceDxeComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified 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 specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ 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 returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ 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 string
+ array indicating the language. This is the
+ language of the driver name that the caller 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 specified 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 and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name 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 valid
+ 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 currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbDeviceDxeGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe.c new file mode 100644 index 0000000000..03bf27d6e5 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe.c @@ -0,0 +1,395 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbDeviceDxe.h"
+#include <Guid/EventGroup.h>
+
+EFI_DRIVER_BINDING_PROTOCOL mUsbDeviceDxeDriverBinding = {
+ UsbDeviceDxeDriverSupported,
+ UsbDeviceDxeDriverStart,
+ UsbDeviceDxeDriverStop,
+ 0x1,
+ NULL,
+ NULL
+};
+
+
+
+VOID
+EFIAPI
+PlatformSpecificInit (
+ VOID
+ )
+{
+ UINTN XhciPciMmBase;
+ EFI_PHYSICAL_ADDRESS XhciMemBaseAddress;
+
+ XhciPciMmBase = MmPciAddress (
+ 0,
+ 0,
+ PCI_DEVICE_NUMBER_XHCI,
+ PCI_FUNCTION_NUMBER_XHCI,
+ 0
+ );
+
+
+ XhciMemBaseAddress = MmioRead32 ((UINTN) (XhciPciMmBase + R_XHCI_MEM_BASE)) & B_XHCI_MEM_BASE_BA;
+ DEBUG ((DEBUG_INFO, "XhciPciMmBase=%x, XhciMemBaseAddress=%x\n", XhciPciMmBase, XhciMemBaseAddress));
+
+ MmioWrite32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_ROLE_CFG0), 0x1310800);
+
+ PmicUSBSwitchControl (TRUE);//conduction USB switch.
+ return;
+}
+
+
+VOID
+EFIAPI
+UsbDeviceDxeExitBootService (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ USB_XDCI_DEV_CONTEXT *UsbXdciDevContext;
+
+ UsbXdciDevContext = (USB_XDCI_DEV_CONTEXT *) Context;
+ DEBUG ((EFI_D_INFO, "UsbDeviceDxeExitBootService enter\n"));
+
+ if (UsbXdciDevContext->XdciPollTimer != NULL) {
+ gBS->SetTimer (UsbXdciDevContext->XdciPollTimer, TimerCancel, 0);
+ gBS->CloseEvent (UsbXdciDevContext->XdciPollTimer);
+ UsbXdciDevContext->XdciPollTimer = 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 = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (USB_CLASSC) / sizeof (UINT8),
+ &UsbClassCReg
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Test whether the controller belongs to USB device type
+ //
+ // 0x0C03FE / 0x0C0380
+ //
+ if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
+ (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
+ ((UsbClassCReg.ProgInterface != PCI_IF_USBDEV) && (UsbClassCReg.ProgInterface != 0x80))) {
+ Status = 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 bus.
+ @retval EFI_ALREADY_STARTED The controller is already controlled by the 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 = NULL;
+
+ //
+ // Provide protocol interface
+ //
+ //
+ // Get the PCI I/O Protocol on PciHandle
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ UsbXdciDevContext = AllocateZeroPool (sizeof (USB_XDCI_DEV_CONTEXT));
+ if (UsbXdciDevContext == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ //
+ // Initialize the driver context
+ //
+ UsbXdciDevContext->StartUpController = FALSE;
+ UsbXdciDevContext->XdciHandle = Controller;
+ UsbXdciDevContext->FirstNodePtr = NULL;
+ UsbXdciDevContext->Signature = EFI_USB_DEV_SIGNATURE;
+
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ R_OTG_BAR0,
+ 1,
+ &UsbXdciDevContext->XdciMmioBarAddr
+ );
+
+ UsbXdciDevContext->XdciMmioBarAddr &= B_OTG_BAR0_BA;
+ DEBUG ((USB_FUIO_DEBUG_INFO, "USB DEV mode IO addr 0x%08x\n", UsbXdciDevContext->XdciMmioBarAddr));
+
+ CopyMem (
+ &(UsbXdciDevContext->UsbFunIoProtocol),
+ &mUsbFunIoProtocol,
+ sizeof (EFI_USBFN_IO_PROTOCOL)
+ );
+
+ CopyMem (
+ &(UsbXdciDevContext->UsbDevModeProtocol),
+ &mUsbDeviceModeProtocol,
+ sizeof (EFI_USB_DEVICE_MODE_PROTOCOL)
+ );
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ UsbDeviceDxeExitBootService,
+ UsbXdciDevContext,
+ &gEfiEventExitBootServicesGuid,
+ &ExitBootServicesEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ Status = 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 protocol, 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 != NULL) {
+ if (UsbXdciDevContext->XdciPollTimer != NULL) {
+ gBS->CloseEvent (UsbXdciDevContext->XdciPollTimer);
+ UsbXdciDevContext->XdciPollTimer = 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 controller
+ 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 = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbFnIoProtocolGuid,
+ &UsbFunIoProtocol,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UsbXdciDevContext = USBFUIO_CONTEXT_FROM_PROTOCOL (UsbFunIoProtocol);
+
+ //
+ // free pool
+ //
+ while (UsbXdciDevContext->FirstNodePtr != NULL) {
+ RemoveNode (UsbFunIoProtocol, UsbXdciDevContext->FirstNodePtr);
+ }
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ UsbXdciDevContext->XdciHandle,
+ &gEfiUsbFnIoProtocolGuid,
+ &UsbXdciDevContext->UsbFunIoProtocol,
+ &gEfiUsbDeviceModeProtocolGuid,
+ &UsbXdciDevContext->UsbDevModeProtocol,
+ NULL
+ );
+
+ if (UsbXdciDevContext->StartUpController == TRUE) {
+ Status = StopController (UsbFunIoProtocol);
+ DEBUG ((USB_FUIO_DEBUG_INFO, "USB DEV mode STOP UsbFnDeInitDevice %r\n", Status));
+ }
+
+ if (UsbXdciDevContext->XdciPollTimer != NULL) {
+ gBS->SetTimer (UsbXdciDevContext->XdciPollTimer, TimerCancel, 0);
+ gBS->CloseEvent (UsbXdciDevContext->XdciPollTimer);
+ UsbXdciDevContext->XdciPollTimer = NULL;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ FreePool (UsbXdciDevContext);
+ return EFI_SUCCESS;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe.h new file mode 100644 index 0000000000..e300fbf153 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe.h @@ -0,0 +1,159 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __USB_DEVICE_DXE_H__
+#define __USB_DEVICE_DXE_H__
+
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DriverLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Protocol/EfiUsbFnIo.h>
+#include <Protocol/UsbDeviceModeProtocol.h>
+#include <PlatformBaseAddresses.h>
+#include <ScAccess.h>
+#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, UsbFunIoProtocol, EFI_USB_DEV_SIGNATURE)
+#define USBUSBD_CONTEXT_FROM_PROTOCOL(a) CR (a, USB_XDCI_DEV_CONTEXT, UsbDevModeProtocol, 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 bus.
+ @retval EFI_ALREADY_STARTED The controller is already controlled by the 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 controller
+ 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/UsbDeviceDxe.inf b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe.inf new file mode 100644 index 0000000000..46c499ab1a --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceDxe.inf @@ -0,0 +1,74 @@ +## @file
+#
+# Copyright (c) 2008 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UsbDeviceDxe
+ FILE_GUID = 42CF2D4A-78B4-4B80-80F9-96A83A630D70
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = UsbDeviceDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = 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 = /D SUPPORT_SUPER_SPEED
+# GCC:*_*_*_CC_FLAGS = -DSUPPORT_SUPER_SPEED
+
+[Depex]
+ TRUE
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceMode.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceMode.c new file mode 100644 index 0000000000..d0358b9dc8 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceMode.c @@ -0,0 +1,1489 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <PlatformBaseAddresses.h>
+#include <ScAccess.h>
+#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 = {
+ //
+ // 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 = FALSE;
+
+STATIC VOID
+XhciSwitchSwid(BOOLEAN enable)
+{
+ UINTN XhciPciMmBase;
+ EFI_PHYSICAL_ADDRESS XhciMemBaseAddress;
+ UINT32 DualRoleCfg0;
+ UINT32 DualRoleCfg1;
+
+ XhciPciMmBase = MmPciAddress (0, 0, PCI_DEVICE_NUMBER_XHCI, PCI_FUNCTION_NUMBER_XHCI, 0);
+ XhciMemBaseAddress = MmioRead32 ((UINTN) (XhciPciMmBase + R_XHCI_MEM_BASE)) & B_XHCI_MEM_BASE_BA;
+ DEBUG ((DEBUG_INFO, "XhciPciMmBase=%x, XhciMemBaseAddress=%x\n", XhciPciMmBase, XhciMemBaseAddress));
+
+ DualRoleCfg0 = MmioRead32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_ROLE_CFG0));
+ if (enable) {
+ DualRoleCfg0 = DualRoleCfg0 | (1 << 24) | (1 << 21) | (1 << 20);
+ DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Set SW ID : 0x%x \n", DualRoleCfg0));
+ }
+ else {
+ DualRoleCfg0 = DualRoleCfg0 & ~(1 << 24) & ~(1 << 21) & ~(1 << 20);
+ DEBUG ((DEBUG_INFO, "DualRoleCfg0 : Clear SW ID : 0x%x \n", DualRoleCfg0));
+ }
+ MmioWrite32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_ROLE_CFG0), DualRoleCfg0);
+
+ DualRoleCfg1 = MmioRead32 ((UINTN)(XhciMemBaseAddress + R_XHCI_MEM_DUAL_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 = (USB_XDCI_DEV_CONTEXT *) Context;
+ EventCount = UsbRegRead ((UINT32)XdciDevContext->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG (0));
+ if (EventCount == 0) {
+ return;
+ }
+
+ LoopCount = 0;
+ PreEventCount = EventCount;
+ while (EventCount != 0) {
+ if (UsbDeviceIsrRoutineTimerBased (mDrvObj.XdciDrvObj) != EFI_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event ISR\n"));
+ }
+ EventCount = UsbRegRead ((UINT32)XdciDevContext->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG (0));
+ if (PreEventCount == EventCount) {
+ LoopCount++;
+ if (LoopCount >= 5) {
+ DEBUG ((DEBUG_INFO, "USB is working on a long event...\n"));
+ break;
+ }
+ } else {
+ LoopCount = 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 subsequent
+ interactions with the XDCI layer.
+
+ @return EFI_SUCCESS if successfully initialized XDCI, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdInit (
+ IN UINT32 MmioBar,
+ IN VOID **XdciHndl
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ USB_DEV_CONFIG_PARAMS ConfigParams;
+
+ XhciSwitchSwid(TRUE);
+
+ DEBUG ((DEBUG_INFO, "UsbdInit start\n"));
+ ConfigParams.ControllerId = USB_ID_DWC_XDCI;
+ ConfigParams.BaseAddress = MmioBar;
+ ConfigParams.Role = USB_ROLE_DEVICE;
+ ConfigParams.Speed = USB_SPEED_SUPER;
+
+ Status = UsbDeviceInit (&ConfigParams, XdciHndl);
+
+ DEBUG ((DEBUG_INFO, "UsbdInit status is %x\n", Status));
+ DEBUG ((DEBUG_INFO, "ConfigParams.BaseAddress 0x%x\n", ConfigParams.BaseAddress));
+
+ 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 = NULL;
+ EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR *EpCompDesc = NULL;
+
+ //
+ // start by clearing all data in the destination
+ //
+ SetMem (EpDest, sizeof(USB_EP_INFO), 0);
+ EpDesc = EpSrc->EndpointDesc;
+ EpCompDesc = EpSrc->EndpointCompDesc;
+
+ if (EpDesc != NULL) {
+ EpDest->EpNum = EpDesc->EndpointAddress & 0x0F; //Bits 0-3 are ep num
+ EpDest->EpDir = ((EpDesc->EndpointAddress & USB_ENDPOINT_DIR_IN) > 0) ? UsbEpDirIn : UsbEpDirOut;
+ EpDest->EpType = EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK;
+ EpDest->MaxPktSize = EpDesc->MaxPacketSize;
+ EpDest->Interval = EpDesc->Interval;
+ }
+ if (EpCompDesc != NULL) {
+ EpDest->MaxStreams = EpCompDesc->Attributes & USB_EP_BULK_BM_ATTR_MASK;
+ EpDest->BurstSize = EpCompDesc->MaxBurst;
+ EpDest->Mult = 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 = EFI_DEVICE_ERROR;
+ USB_EP_INFO EpInfo;
+
+ UsbdSetEpInfo (&EpInfo, DevEpInfo);
+ Status = 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 = (UINT8)XferReq->EpInfo.EpNum;
+ XferInfo.EndpointDir = XferReq->EpInfo.EpDir;
+ XferInfo.EndpointType = XferReq->EpInfo.EpType;
+ XferInfo.Buffer = XferReq->XferBuffer;
+ XferInfo.Length = XferReq->ActualXferLen;
+
+ //
+ // If this is a non-control transfer complete, notify the class driver
+ //
+ if (XferInfo.EndpointNum > 0) {
+ if (mDrvObj.UsbdDevObj->DataCallback != 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 = 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 == NULL) {
+ TxReq.EpInfo.EpNum = 0;
+ TxReq.EpInfo.EpDir = UsbEpDirIn;
+ }
+
+ //
+ // setup the trasfer request
+ //
+ TxReq.XferBuffer = IoReq->IoInfo.Buffer;
+ TxReq.XferLen = IoReq->IoInfo.Length;
+ TxReq.XferDone = 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, TxReq.EpInfo.MaxPktSize));
+
+ Status = 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 = EFI_DEVICE_ERROR;
+ USB_XFER_REQUEST RxReq;
+ UINT32 ReqPacket;
+
+ DEBUG ((DEBUG_INFO, "RX REQUEST in: IoReq->IoInfo.Length: 0x%x\n", IoReq->IoInfo.Length));
+ DEBUG ((DEBUG_INFO, "RX REQUEST in: MaxPacketSize: 0x%x\n", IoReq->EndpointInfo.EndpointDesc->MaxPacketSize));
+
+ if (IoReq->EndpointInfo.EndpointDesc->MaxPacketSize == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // set endpoint data
+ //
+ UsbdSetEpInfo (&(RxReq.EpInfo), &(IoReq->EndpointInfo));
+
+ //
+ // setup the trasfer request
+ //
+ RxReq.XferBuffer = IoReq->IoInfo.Buffer;
+
+ //
+ // Transfer length should be multiple of USB packet size.
+ //
+ ReqPacket = IoReq->IoInfo.Length / IoReq->EndpointInfo.EndpointDesc->MaxPacketSize;
+ ReqPacket = ((IoReq->IoInfo.Length % IoReq->EndpointInfo.EndpointDesc->MaxPacketSize) == 0)? ReqPacket : ReqPacket + 1;
+ RxReq.XferLen = ReqPacket * IoReq->EndpointInfo.EndpointDesc->MaxPacketSize;
+
+ RxReq.XferDone = 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 = 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 = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdResetEvtHndlr\n"));
+
+ //
+ // reset device address to 0
+ //
+ Status = 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 = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdConnDoneEvtHndlr\n"));
+
+ //
+ //reset device address to 0
+ //
+ Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDCI\n"));
+ }
+
+ //
+ // set the device state to attached/connected
+ //
+ mDrvObj.State = 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 = 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 = 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, UsbdResetEvtHndlr) != EFI_SUCCESS) {
+ goto UdciRegCallbackError;
+ }
+
+ if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_CONNECTION_DONE, UsbdConnDoneEvtHndlr) != EFI_SUCCESS) {
+ goto UdciRegCallbackError;
+ }
+
+ if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_SETUP_PKT_RECEIVED, UsbdSetupEvtHndlr) != EFI_SUCCESS) {
+ goto UdciRegCallbackError;
+ }
+
+ if (UsbDeviceRegisterCallback (XdciHndl, USB_DEVICE_XFER_NRDY, UsbdNrdyEvtHndlr) != 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 to
+ @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 otherwise
+
+**/
+EFI_STATUS
+UsbdGetConfigDesc (
+ IN VOID *Buffer,
+ IN UINT8 DescIndex,
+ IN UINT32 ReqLen,
+ IN UINT32 *DataLen
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINT8 NumConfigs = 0;
+ UINT32 ConfigLen = 0;
+ USB_DEVICE_CONFIG_OBJ *ConfigObj = NULL;
+ VOID *Descriptor = 0;
+ UINT32 Length = 0;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc()\n"));
+
+ //
+ // For a CONFIGURATION request we send back all descriptors branching out
+ // from this descriptor including the INTERFACE and ENDPOINT descriptors
+ //
+ //
+ // Verify the requested configuration exists - check valid index
+ //
+ NumConfigs = mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations;
+
+ if (DescIndex < NumConfigs) {
+ //
+ // get the configuration object using the index Offset
+ //
+ ConfigObj = (mDrvObj.UsbdDevObj->ConfigObjs + DescIndex);
+ //
+ // get the complete configuration Buffer block including Interface and Endpoint data
+ //
+ Descriptor = ConfigObj->ConfigAll;
+ //
+ // The config descriptor TotalLength has the full value for all desc Buffers
+ //
+ ConfigLen = ConfigObj->ConfigDesc->TotalLength;
+ //
+ // copy the data to the output Buffer
+ //
+ Length = MIN (ReqLen, ConfigLen);
+ CopyMem (Buffer, Descriptor, Length);
+ *DataLen = Length;
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetConfigDesc() - Invalid Config index: %i\n", DescIndex));
+ }
+
+ if (Status == EFI_SUCCESS) {
+ if (ConfigObj != 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 otherwise
+
+**/
+EFI_STATUS
+UsbdSetConfig (
+ UINT8 CfgValue
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINT8 numConfigs = 0;
+ USB_DEVICE_CONFIG_OBJ *pConfigObj = NULL;
+ USB_DEVICE_INTERFACE_OBJ *pIfObj = NULL;
+ USB_DEVICE_ENDPOINT_OBJ *pEpObj = NULL;
+ UINT8 cfgItr = 0;
+ UINT8 ifItr = 0;
+ UINT8 epItr = 0;
+ USB_DEVICE_ENDPOINT_INFO EpInfo;
+ USB_EP_INFO UsbEpInfo;
+
+ DEBUG ((DEBUG_INFO, "UsbdSetConfig()\n"));
+ //
+ // Verify the requested configuration exists - check valid index
+ //
+ numConfigs = mDrvObj.UsbdDevObj->DeviceDesc->NumConfigurations;
+
+ if (CfgValue != 0) {
+ //
+ // Search for a matching configuration
+ //
+ for (cfgItr = 0; cfgItr < numConfigs; cfgItr++) {
+ pConfigObj = (mDrvObj.UsbdDevObj->ConfigObjs + cfgItr);
+ if (pConfigObj->ConfigDesc->ConfigurationValue == CfgValue) {
+
+ //
+ // Set the active configuration object
+ //
+ mDrvObj.ActiveConfigObj = pConfigObj;
+ //
+ // Find all interface objects for this configuration
+ //
+ for (ifItr = 0; ifItr < pConfigObj->ConfigDesc->NumInterfaces; ifItr++) {
+ pIfObj = (pConfigObj->InterfaceObjs + ifItr);
+ //
+ // Configure the Endpoints in the XDCI
+ //
+ for (epItr = 0; epItr < pIfObj->InterfaceDesc->NumEndpoints; epItr++) {
+ pEpObj = (pIfObj->EndpointObjs + epItr);
+
+ EpInfo.EndpointDesc = pEpObj->EndpointDesc;
+ EpInfo.EndpointCompDesc = pEpObj->EndpointCompDesc;
+
+ if (UsbdInitEp (mDrvObj.XdciDrvObj, &EpInfo) == EFI_SUCCESS) {
+ UsbdSetEpInfo(&UsbEpInfo, &EpInfo);
+ if (UsbDeviceEpEnable (mDrvObj.XdciDrvObj, &UsbEpInfo) == EFI_SUCCESS) {
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to enable endpoint\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetConfig() - Failed to initialize endpoint\n"));
+ }
+ }
+ }
+ //
+ // Let the class driver know it is configured
+ //
+ if (Status == EFI_SUCCESS) {
+ if (mDrvObj.UsbdDevObj->ConfigCallback != NULL) {
+ mDrvObj.UsbdDevObj->ConfigCallback (CfgValue);
+ }
+ }
+
+ mDrvObj.State = 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 value 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_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdGetConfig (
+ VOID *Buffer,
+ UINT32 ReqLen,
+ UINT32 *DataLen
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetConfig()\n"));
+
+ if (ReqLen >= 1) { // length of data expected must be 1
+ if (mDrvObj.ActiveConfigObj != NULL) { // assure we have a config active
+ *DataLen = 1; // one byte for ConfigurationValue
+ *(UINT8*)Buffer = mDrvObj.ActiveConfigObj->ConfigDesc->ConfigurationValue;
+
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetConfig() - No active configuration available\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 to
+ @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 otherwise
+
+**/
+EFI_STATUS
+UsbdGetStringDesc (
+ VOID *Buffer,
+ UINT8 DescIndex,
+ UINT16 LangId,
+ UINT32 ReqLen,
+ UINT32 *DataLen
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ UINT32 Length = 0;
+ USB_STRING_DESCRIPTOR *StringDesc;
+ UINT8 Index = 0;
+ UINT8 StrLangEntries = 0;
+ BOOLEAN StrLangFound = FALSE;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Index: 0x%x, LangId: 0x%x, ReqLen: 0x%x\n", DescIndex, LangId, ReqLen));
+
+ //
+ // index zero of the string table contains the supported language codes
+ //
+ if (DescIndex == 0) {
+ StringDesc = (mDrvObj.UsbdDevObj->StringTable);
+ Length = MIN (ReqLen, StringDesc->Length);
+ CopyMem (Buffer, StringDesc, Length);
+ *DataLen = Length;
+ Status = EFI_SUCCESS;
+ } else {
+
+ //
+ // Verify the requested language ID is supported. String descriptor Zero
+ // (First entry in the string table) is expected to contain the language list.
+ // The requested language ID is specified in the Index member of the request.
+ //
+ StringDesc = mDrvObj.UsbdDevObj->StringTable; // get language string descriptor
+ StrLangEntries = ((StringDesc->Length - 2) >> 1);
+ DEBUG ((DEBUG_INFO, "StrLangEntries=%x\n", StrLangEntries));
+
+ DEBUG ((DEBUG_INFO, "Looking LangID: \n"));
+
+ for (Index = 0; Index < StrLangEntries; Index++) {
+ DEBUG ((DEBUG_INFO, "LangID [%x]= %x\n", Index, StringDesc->LangID [Index]));
+
+ if (StringDesc->LangID [Index] == LangId) {
+ DEBUG ((DEBUG_INFO, "Found it\n"));
+ StrLangFound = TRUE;
+ }
+ }
+
+ //
+ // If we found a matching language, attempt to get the string index requested
+ //
+ if (StrLangFound == TRUE) {
+ DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: StrLangFound=Found, DescIndex=%x, StrTblEntries=%x\n", DescIndex, mDrvObj.UsbdDevObj->StrTblEntries));
+
+ if (DescIndex < mDrvObj.UsbdDevObj->StrTblEntries) {
+ //
+ // get the string descriptor for the requested index
+ //
+ StringDesc = (mDrvObj.UsbdDevObj->StringTable + DescIndex);
+
+ Length = MIN (ReqLen, StringDesc->Length);
+ DEBUG ((DEBUG_INFO, "ReqLen=%x, StringLength=%x, Length=%x\n", ReqLen, StringDesc->Length, Length));
+
+ CopyMem (Buffer, StringDesc, Length);
+ *DataLen = Length;
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Invalid String index in USB_REQ_GET_DESCRIPTOR request\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdGetStringDesc: Unsupported String Language ID for USB_REQ_GET_DESCRIPTOR request\n"));
+ }
+ }
+
+ if (Status == 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 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 descritor successfully copied, EFI_DEVICE_ERROR otherwise
+
+**/
+EFI_STATUS
+UsbdGetBOSDesc (
+ IN VOID *Buffer,
+ IN UINT32 ReqLen,
+ IN UINT32 *DataLen
+ )
+{
+ EFI_USB_BOS_DESCRIPTOR *BosDesc = 0;
+ UINT32 Length = 0;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetBOSDesc()\n"));
+
+ BosDesc = mDrvObj.UsbdDevObj->BosDesc;
+ Length = MIN (ReqLen, mDrvObj.UsbdDevObj->BosDesc->TotalLength);
+
+ CopyMem(Buffer, BosDesc, Length);
+ *DataLen = 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 to
+ @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 otherwise
+
+**/
+EFI_STATUS
+UsbdGetStatus (
+ VOID *Buffer,
+ UINT8 ReqType,
+ UINT32 ReqLen,
+ UINT32 *DataLen
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdGetStatus()\n"));
+
+ if (ReqLen >= 2) { // length of data must be at least 2 bytes
+ switch (ReqType & USB_TARGET_MASK) {
+ case USB_TARGET_DEVICE:
+ *DataLen = 2; // two byte for status
+ *(UINT16*)Buffer = USB_STATUS_SELFPOWERED;
+ Status = 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 = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdSetAddress: setting address: 0x%x\n", Address));
+
+ if (Address <= 0x7F) { // address must not be > 127
+ mDrvObj.Address = Address;
+
+ //
+ // Configure Address in the XDCI
+ //
+ Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, mDrvObj.Address);
+ if (!EFI_ERROR (Status)) {
+ mDrvObj.State = 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 = EFI_DEVICE_ERROR;
+ UINT8 DescIndex = 0;
+ USB_DEVICE_DESCRIPTOR *DevDesc = 0;
+
+ //
+ // Initialize the IO object
+ //
+ mCtrlIoReq.IoInfo.Length = 0;
+
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr start\n"));
+ PrintDeviceRequest (CtrlRequest);
+
+ //
+ // Handle Standard Device Requests
+ //
+ if ((CtrlRequest->RequestType & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) {
+ switch (CtrlRequest->Request) {
+ case USB_REQ_GET_DESCRIPTOR:
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Host requests get descriptor\n"));
+ if (CtrlRequest->RequestType == USB_RT_TX_DIR_D_TO_H) {
+ DescIndex = (CtrlRequest->Value & 0xff); // low byte is the index requested
+ switch (CtrlRequest->Value >> 8) { // high byte contains request type
+ case USB_DESC_TYPE_DEVICE:
+ DEBUG ((DEBUG_INFO, "Descriptor tyep: Device\n"));
+ DevDesc = mDrvObj.UsbdDevObj->DeviceDesc;
+ //
+ // copy the data to the output Buffer
+ //
+ mCtrlIoReq.IoInfo.Length = MIN (CtrlRequest->Length, DevDesc->Length);
+ CopyMem (mCtrlIoReq.IoInfo.Buffer, DevDesc, mCtrlIoReq.IoInfo.Length);
+ PrintDeviceDescriptor (DevDesc);
+ break;
+
+ case USB_DESC_TYPE_CONFIG:
+ DEBUG ((DEBUG_INFO, "Descriptor tyep: Configuration\n"));
+ Status = UsbdGetConfigDesc (
+ mCtrlIoReq.IoInfo.Buffer,
+ DescIndex,
+ CtrlRequest->Length,
+ &(mCtrlIoReq.IoInfo.Length)
+ );
+ break;
+
+ case USB_DESC_TYPE_STRING:
+ DEBUG ((DEBUG_INFO, "Descriptor tyep: String\n"));
+ Status = 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 = 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_GET_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 == USB_RT_TX_DIR_D_TO_H) {
+ Status = UsbdGetConfig (mCtrlIoReq.IoInfo.Buffer, CtrlRequest->Length, &(mCtrlIoReq.IoInfo.Length));
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_GET_CONFIG request\n"));
+ }
+ break;
+
+ case USB_REQ_SET_CONFIG:
+ DEBUG ((DEBUG_INFO, "USB_REQ_SET_CONFIG\n"));
+ if (CtrlRequest->RequestType == USB_RT_TX_DIR_H_TO_D) {
+ Status = UsbdSetConfig ((UINT8)CtrlRequest->Value);
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_SET_CONFIG request\n"));
+ }
+ break;
+
+ case USB_REQ_SET_ADDRESS:
+ DEBUG ((DEBUG_INFO, "USB_REQ_SET_ADDRESS\n"));
+ if (CtrlRequest->RequestType == USB_RT_TX_DIR_H_TO_D) {
+ Status = UsbdSetAddress ((UINT8)CtrlRequest->Value);
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_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 = UsbdGetStatus (mCtrlIoReq.IoInfo.Buffer, CtrlRequest->RequestType, CtrlRequest->Length, &(mCtrlIoReq.IoInfo.Length));
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Invalid direction for USB_REQ_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 handling
+ //
+ // Forward request to class driver
+ //
+ DEBUG ((DEBUG_INFO, "UsbdSetupHdlr: Class/Vendor Request\n"));
+ if (mDrvObj.UsbdDevObj->SetupCallback != NULL) {
+ mDrvObj.UsbdDevObj->SetupCallback (CtrlRequest, &(mCtrlIoReq.IoInfo));
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "dataLen=%x\n", mCtrlIoReq.IoInfo.Length));
+ //
+ // Transfer data according to request if necessary
+ //
+ if (mCtrlIoReq.IoInfo.Length> 0) {
+ Status = 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 = 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 otherwise
+
+**/
+EFI_STATUS
+UsbdConnDoneHdlr (
+ VOID
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr()\n"));
+
+ //
+ // reset device address to 0
+ //
+ Status = UsbDeviceSetAddress (mDrvObj.XdciDrvObj, 0x0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "UsbdConnDoneHdlr() - Failed to set address in XDCI\n"));
+ }
+
+ //
+ // set the device state to attached/connected
+ //
+ mDrvObj.State = 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 != 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 device
+
+ @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 = EFI_SUCCESS;
+
+ //
+ // allocate Tx Buffer
+ //
+ mCtrlIoReq.IoInfo.Buffer = AllocateZeroPool (USB_EPO_MAX_PKT_SIZE_ALL);
+ if (mCtrlIoReq.IoInfo.Buffer != NULL) {
+ mDrvObj.UsbdDevObj = UsbdDevObj;
+ mDrvObj.ActiveConfigObj = NULL;
+ mDrvObj.Address = 0;
+ mDrvObj.State = UsbDevStateInit;
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceBind() - Failed to allocate IO Buffer\n"));
+ Status = 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 = NULL;
+ mDrvObj.ActiveConfigObj = NULL;
+ mDrvObj.Address = 0;
+ mDrvObj.State = UsbDevStateOff;
+ mDrvObj.XdciInitialized = 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 = EFI_DEVICE_ERROR;
+ USB_XDCI_DEV_CONTEXT *XdciDevContext;
+
+ XdciDevContext = USBUSBD_CONTEXT_FROM_PROTOCOL (This);
+
+ //
+ // can only run if XDCI is initialized
+ //
+ if ((mDrvObj.XdciInitialized == TRUE)) {
+
+ if ((mDrvObj.State == UsbDevStateConfigured) && (XdciDevContext->XdciPollTimer == NULL)) {
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ UsbdMonitorEvents,
+ XdciDevContext,
+ &XdciDevContext->XdciPollTimer
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->SetTimer (XdciDevContext->XdciPollTimer, TimerPeriodic, EFI_TIMER_PERIOD_MILLISECONDS (20));
+ DEBUG ((EFI_D_ERROR, "UsbDeviceRun Create Event\n"));
+ }
+ }
+
+ mXdciRun = TRUE; // set the run flag to active
+ Status = EFI_SUCCESS;
+
+ //
+ // start the Event processing loop
+ //
+ while (TRUE) {
+ if (XdciDevContext->XdciPollTimer == NULL) {
+ if (UsbDeviceIsrRoutine (mDrvObj.XdciDrvObj) != EFI_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceRun() - Failed to execute event ISR\n"));
+ }
+ }
+
+ //
+ // Check if a run cancel request exists, if so exit processing loop
+ //
+ if (mXdciRun == FALSE) {
+ if (XdciDevContext->XdciPollTimer != NULL) {
+ DEBUG ((EFI_D_ERROR, "UsbDeviceRun close Event\n"));
+ gBS->SetTimer (XdciDevContext->XdciPollTimer, TimerCancel, 0);
+ gBS->CloseEvent (XdciDevContext->XdciPollTimer);
+ XdciDevContext->XdciPollTimer = NULL;
+ }
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_INFO, "UsbDeviceRun() - processing was cancelled\n"));
+ break;
+ }
+
+ //
+ // check for timeout
+ //
+ if (TimeoutMs == 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 = 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 = EFI_DEVICE_ERROR;
+ USB_XDCI_DEV_CONTEXT *XdciDevContext;
+
+ XdciDevContext = USBUSBD_CONTEXT_FROM_PROTOCOL (This);
+
+ PlatformSpecificInit ();
+
+ if (mDrvObj.XdciInitialized == FALSE) {
+ if (XdciDevContext->XdciMmioBarAddr != 0) {
+
+ //
+ // Initialize device controller driver
+ //
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Initializing Controller...\n"));
+
+ //
+ // Initialize the device controller interface
+ //
+ if (UsbdInit ((UINT32)XdciDevContext->XdciMmioBarAddr, &mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
+
+ //
+ // Setup callbacks
+ //
+ if (UsbdRegisterCallbacks (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
+
+ mDrvObj.XdciInitialized = TRUE;
+ Status = EFI_SUCCESS;
+
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Controller initialization complete\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to register UDCI callbacks\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - Failed to initialize UDCI\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI MMIO BAR not set\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitXdci() - XDCI already initialized\n"));
+ Status = EFI_ALREADY_STARTED;
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+UsbDeviceConnect(
+ IN EFI_USB_DEVICE_MODE_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbDeviceConnect \n"));
+ if (UsbXdciDeviceConnect (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
+ Status = EFI_SUCCESS;
+ }
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+UsbDeviceDisConnect (
+ IN EFI_USB_DEVICE_MODE_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbDeviceDisConnect \n"));
+ if (UsbDeviceDisconnect (mDrvObj.XdciDrvObj) == EFI_SUCCESS) {
+ mDrvObj.State = UsbDevStateInit;
+ Status = 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 = 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 = UsbdEpRxData (mDrvObj.XdciDrvObj, IoRequest);
+ return Status;
+}
+
+
+//
+// The Runtime UsbDeviceMode Protocol instance produced by this driver
+//
+EFI_USB_DEVICE_MODE_PROTOCOL mUsbDeviceModeProtocol = {
+ UsbDeviceInitXdci,
+ UsbDeviceConnect,
+ UsbDeviceDisConnect,
+ UsbDeviceEpTxData,
+ UsbDeviceEpRxData,
+ UsbDeviceBind,
+ UsbDeviceUnbind,
+ UsbDeviceRun,
+ UsbDeviceStop
+};
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceMode.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceMode.h new file mode 100644 index 0000000000..54459744bc --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbDeviceMode.h @@ -0,0 +1,39 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _USB_DEVICE_MODE_DXE_H_
+#define _USB_DEVICE_MODE_DXE_H_
+
+#include <Uefi.h>
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UsbDeviceLib.h>
+#include <Protocol/UsbDeviceModeProtocol.h>
+#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/UsbFuncIo.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFuncIo.c new file mode 100644 index 0000000000..9a156ba9b4 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFuncIo.c @@ -0,0 +1,2219 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbDeviceDxe.h"
+
+//
+// 16 bytes in a guid x 2 characters per byte, 4 chars for dashes and a NUL
+//
+#define CHARS_IN_GUID (sizeof(GUID) * 2 + 4 + 1)
+
+//
+// Strings that get sent with the USB Connection
+//
+static CHAR16 mUsbFnDxeMfgString[] = L"Intel Corporation";
+static CHAR16 mUsbFnDxeProductString[] = L"Broxton";
+static CHAR16 mUsbFnDxeSerialNumber[] = L"INT123456";
+
+//
+// Duplicated from MiscSystemManufacturerData.c Some parts of it will
+// replaced with device-specific unique values.
+//
+static GUID mSmBiosUniqueGuid = {
+ 0x5e24fe9c, 0xc8d0, 0x45bd, 0xa7, 0x9f, 0x54, 0xea, 0x5f, 0xbd, 0x3d, 0x97
+ };
+
+EFI_USBFN_IO_PROTOCOL mUsbFunIoProtocol = {
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+
+ EventCount = UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG(0));
+
+ DbBufPtr = (UINT32*)(UINTN)XdciCorePtr->CurrentEventBuffer;
+ XdciCorePtr = 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 = 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 instance.
+ @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 = 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 = Not determined
+ // 0001 = SDP Attached
+ // 0010 = DCP Attached
+ // 0011 = CDP Attached
+ // 0100 = ACA Attached
+ // 0101 = SE1 Attached
+ // 0110 = MHL Attached
+ // 0111 = Floating D+/D- Attached
+ // 1000 = Other Attached
+ // 1001 = DCP detected by ext. USB PHY
+ // 1010-1111 = Rsvd
+ // Reset: 0000B
+ //
+
+ Value8 =PmicRead8 (0x5E, 0X29);
+ if ((Value8 & 0x03) != 0x02) {
+ *PortType = EfiUsbUnknownPort;
+ Status = EFI_NOT_READY;
+ goto out;
+ }
+
+ Value8 = Value8 >> 2 & 0x0f;
+ Status = EFI_SUCCESS;
+ switch (Value8) {
+ case 1:
+ *PortType = EfiUsbStandardDownstreamPort;
+ break;
+ case 2:
+ *PortType = EfiUsbDedicatedChargingPort;
+ break;
+ case 3:
+ *PortType = EfiUsbChargingDownstreamPort;
+ break;
+
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ *PortType = EfiUsbUnknownPort;
+ break;
+ case 0:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ *PortType = EfiUsbUnknownPort;
+ Status = 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 bytes
+ and returns the address of the allocated memory that satisfies underlying
+ controller requirements in the location referenced by Buffer.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @param[in] Size The number of bytes to allocate for the transfer
+ Buffer.
+ @param[in] Buffer A pointer to a pointer to the allocated Buffer
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ if (Size == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ErrorExit;
+ }
+
+ AllocateBufferPtr = AllocateZeroPool (Size);
+
+ if (AllocateBufferPtr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ //
+ // Create new node
+ //
+ Status = InsertNewNodeToHead (This, &NodePtr);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ NodePtr->Size = Size;
+ NodePtr->AllocatePtr = AllocateBufferPtr;
+
+ *Buffer = AllocateBufferPtr;
+
+ DEBUG ((USB_FUIO_DEBUG_INFO, "AllocateTransferBuffer addr 0x%08x\n", AllocateBufferPtr));
+ DEBUG ((USB_FUIO_DEBUG_INFO, "AllocateTransferBuffer - Exit\n"));
+ return EFI_SUCCESS;
+
+ErrorExit:
+
+ DEBUG ((USB_FUIO_DEBUG_ERROR, "AllocateTransferBuffer - ERRROR %r\n",Status));
+ return Status;
+}
+
+
+/**
+ Deallocates the memory allocated for the transfer Buffer by
+ AllocateTransferBuffer function.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "FreeTransferBuffer - Entry\n"));
+
+ Status = 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 descriptors.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @param[in] DeviceInfo A pointer to EFI_USBFN_DEVICE_INFO instance.
+
+ @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 to
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ Status = 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 = EFI_SUCCESS;
+ if (DeviceInfo == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto FUNC_EXIT;
+ }
+
+ UsbFuncIoDevPtr->DevInfoPtr->DeviceDescriptor = DeviceInfo->DeviceDescriptor;
+
+ //
+ // Set Configure table
+ //
+ if (DeviceInfo->DeviceDescriptor->NumConfigurations > 1) {
+ DEBUG ((EFI_D_ERROR, "!!!Error ConfigNum over '1' %d\n", DeviceInfo->DeviceDescriptor->NumConfigurations));
+ }
+ UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor = DeviceInfo->ConfigInfoTable[0]->ConfigDescriptor;
+ UsbFuncIoDevPtr->IndexPtrConfig.InterfaceInfoTable[0] = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0];
+
+ //
+ // Set Interface
+ //
+ if (DeviceInfo->ConfigInfoTable[0]->ConfigDescriptor->NumInterfaces > 1) {
+ DEBUG ((EFI_D_ERROR, "!!!Error NumInterfaces[0] over '1' %d\n", DeviceInfo->ConfigInfoTable[0]->ConfigDescriptor->NumInterfaces));
+ }
+ UsbFuncIoDevPtr->IndexPtrInteface.InterfaceDescriptor = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->InterfaceDescriptor;
+
+ //
+ // Set Endpoint
+ //
+ if (UsbFuncIoDevPtr->IndexPtrInteface.InterfaceDescriptor->NumEndpoints > 2) {
+ DEBUG ((EFI_D_ERROR, "!!!Error NumEndPoint[0] over '2' %d\n", UsbFuncIoDevPtr->IndexPtrInteface.InterfaceDescriptor->NumEndpoints));
+ }
+
+ UsbFuncIoDevPtr->IndexPtrInEp.EndpointCompDesc = NULL;
+ UsbFuncIoDevPtr->IndexPtrOutEp.EndpointCompDesc = NULL;
+
+ if ((DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[0]->EndpointAddress & USB_ENDPOINT_DIR_IN) != 0) {
+ UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[0];
+ UsbFuncIoDevPtr->IndexPtrOutEp.EndpointDesc = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[1];
+ } else {
+ UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[1];
+ UsbFuncIoDevPtr->IndexPtrOutEp.EndpointDesc = DeviceInfo->ConfigInfoTable[0]->InterfaceInfoTable[0]->EndpointDescriptorTable[0];
+ }
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, " In Ep Num 0x%02x\n", UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc->EndpointAddress));
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, " Out Ep Num 0x%02x\n", UsbFuncIoDevPtr->IndexPtrOutEp.EndpointDesc->EndpointAddress));
+
+FUNC_EXIT:
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "ConfigureEnableEndpoints - exit %r\n", Status));
+ 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 instance.
+ @param[in] EndpointType Endpoint type as defined as EFI_USB_ENDPOINT_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 to
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ DevCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = DevCorePtr->ControllerHandle;
+ Status = EFI_SUCCESS;
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointMaxPacketSize - Entry\n"));
+
+ switch (EndpointType) {
+ case UsbEndpointControl:
+#ifdef SUPPORT_SUPER_SPEED
+ *MaxPacketSize = USB_EP0_MAX_PKT_SIZE_SS; // Default to super Speed
+#else
+ *MaxPacketSize = USB_EP0_MAX_PKT_SIZE_HS; // Default to high Speed
+#endif
+ break;
+
+ case UsbEndpointBulk:
+#ifdef SUPPORT_SUPER_SPEED
+ *MaxPacketSize = USB_BULK_EP_PKT_SIZE_SS; // Default to super Speed
+#else
+ *MaxPacketSize = USB_BULK_EP_PKT_SIZE_HS; // Default to high Speed
+#endif
+ break;
+
+ case UsbEndpointInterrupt:
+ *MaxPacketSize = 1;
+ break;
+
+ case UsbEndpointIsochronous:
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointMaxPacketSize - Exit %r\n", Status));
+ return Status;
+}
+
+
+/**
+ Returns the maximum supported transfer size.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @param[in] MaxTransferSize The maximum supported transfer size, in bytes.
+
+ @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 to
+ 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 = 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 requested
+ information as a Unicode string. What string 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 = EFI_SUCCESS;
+ CHAR16 UuidString[CHARS_IN_GUID];
+ UINTN CharsCopied;
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "+GetDeviceSerialNumber\n"));
+ //
+ // check bounds
+ //
+ if (*BufferSize < sizeof(UuidString)) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ *BufferSize = 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 time 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 = UnicodeSPrint(UuidString, sizeof(UuidString), L"%g", &mSmBiosUniqueGuid);
+ if (CharsCopied != (CHARS_IN_GUID - 1))
+ {
+ Status = EFI_BUFFER_TOO_SMALL;
+ *BufferSize = 0;
+ goto Error;
+ }
+ CopyMem(Buffer, UuidString, sizeof(UuidString));
+ *BufferSize = sizeof(UuidString);
+
+Error:
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "-GetDeviceSerialNumber, Status = 0x%08x\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 instance.
+ @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 requested
+ information as a Unicode string. What string 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 to
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ Status = EFI_SUCCESS;
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "GetDeviceInfo - Entry\n"));
+
+ if ((BufferSize == 0) || (Buffer == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto FUN_EXIT;
+ }
+
+ switch (Id) {
+
+ //
+ // FIXME: Get real serial number of board
+ //
+ case EfiUsbDeviceInfoSerialNumber:
+ if (*BufferSize < sizeof(mUsbFnDxeSerialNumber)) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ *BufferSize = 0;
+ goto FUN_EXIT;
+ }
+ CopyMem(Buffer, mUsbFnDxeSerialNumber, sizeof(mUsbFnDxeSerialNumber));
+ *BufferSize = sizeof(mUsbFnDxeSerialNumber);
+ break;
+
+ case EfiUsbDeviceInfoManufacturerName:
+ if (*BufferSize < sizeof(mUsbFnDxeMfgString)) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ *BufferSize = 0;
+ goto FUN_EXIT;
+ }
+ CopyMem(Buffer, mUsbFnDxeMfgString, sizeof(mUsbFnDxeMfgString));
+ *BufferSize = sizeof(mUsbFnDxeMfgString);
+ break;
+
+ case EfiUsbDeviceInfoProductName:
+ if (*BufferSize < sizeof(mUsbFnDxeProductString)) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ *BufferSize = 0;
+ goto FUN_EXIT;
+ }
+ CopyMem(Buffer, mUsbFnDxeProductString, sizeof(mUsbFnDxeProductString));
+ *BufferSize = sizeof(mUsbFnDxeProductString);
+ break;
+
+ case EfiUsbDeviceInfoUnknown:
+ default:
+ Status = EFI_UNSUPPORTED;
+ *BufferSize = 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 instance.
+ @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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ //
+ // *Vid = 0x8086
+ // *Pid = 0x0A65
+ //
+ *Vid = UsbFuncIoDevPtr->VendorId;
+ *Pid = UsbFuncIoDevPtr->DeviceId;
+ return EFI_SUCCESS;
+}
+
+/**
+ Aborts transfer on the specified endpoint.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @param[in] EndpointIndex Indicates the endpoint on which the ongoing
+ 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 to
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ Status = EFI_SUCCESS;
+
+ if (UsbFuncIoDevPtr->DevResetFlag == TRUE) {
+ return Status;
+ }
+
+ EpInfo.EpNum = EndpointIndex;
+ EpInfo.EpDir = Direction? UsbEpDirIn : UsbEpDirOut;
+
+ Status = 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 instance.
+ @param[in] EndpointIndex Indicates the endpoint on which the ongoing
+ transfer needs to be canceled.
+ @param[in] Direction Direction of the endpoint.
+ @param[in] State Boolean, true value indicates that the endpoint
+ 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 to
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointStallState - Entry\n"));
+
+ EndPoint = UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn : UsbEpDirOut);
+
+ XdciCorePtr = UsbFuncIoDevPtr->XdciDrvIfHandle;
+
+ if (XdciCorePtr->EpHandles[EndPoint].State == USB_EP_STATE_STALLED) {
+ *State = TRUE;
+ } else {
+ *State = 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ Status = EFI_SUCCESS;
+
+ Status = UsbDeviceSetAddress (UsbDeviceCorePtr, (UINT32)Address);
+
+ if (Status != EFI_SUCCESS) {
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT_SET_ADDRESS;
+ }
+
+ Status = UsbDeviceEp0TxStatus (UsbDeviceCorePtr);
+
+ if (Status != EFI_SUCCESS) {
+ Status = 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", InterFaceIndex));
+
+ UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ Status = EFI_SUCCESS;
+
+ InterfaceNum = UsbFuncIoDevPtr->IndexPtrConfig.ConfigDescriptor->NumInterfaces;
+ 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->ConfigurationValue
+ ));
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - InterfaceNum 0x%04x \n", InterfaceNum));
+ if (InterfaceNum < InterFaceIndex) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT__SET_CONFIGURE;
+ }
+
+ //
+ // Arry strart form '0', Index start from '1'.
+ //
+ InterfaceInfoPtr = UsbFuncIoDevPtr->IndexPtrConfig.InterfaceInfoTable[InterFaceIndex - 1];
+ EndPointNum = InterfaceInfoPtr->InterfaceDescriptor->NumEndpoints;
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbSetconfigure - Total EP NUM 0x%04x \n", EndPointNum));
+
+ for (EndPointIndex = 0; EndPointIndex < EndPointNum; EndPointIndex++) {
+ EpDescInfo.EndpointDesc = InterfaceInfoPtr->EndpointDescriptorTable[EndPointIndex];
+ EpDescInfo.EndpointCompDesc = NULL;
+ UsbFnSetEpInfo (&EpInfo, &EpDescInfo);
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "EndpointAddress 0x%02x\n", EpDescInfo.EndpointDesc->EndpointAddress));
+
+ if (UsbDeviceInitEp (UsbDeviceCorePtr, &EpInfo) == EFI_SUCCESS) {
+ if (UsbDeviceEpEnable (UsbDeviceCorePtr, &EpInfo) == EFI_SUCCESS) {
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ DEBUG ((DEBUG_INFO, "UsbDeviceEpEnable() - Failed to enable endpoint\n"));
+ }
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitEp() - Failed to initialize endpoint\n"));
+ }
+ }
+
+ Status = UsbDeviceEp0TxStatus (UsbDeviceCorePtr);
+
+ if (Status != EFI_SUCCESS) {
+ Status = 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 instance.
+ @param[in] EndpointIndex Indicates the endpoint on which the ongoing
+ transfer needs to be canceled.
+ @param[in] Direction Direction of the endpoint.
+ @param[in] State Requested stall state on the specified endpoint.
+ 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 to
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "SetEndpointStallState - Entry\n"));
+ Status = EFI_SUCCESS;
+
+ pEpInfo.EpNum = EndpointIndex;
+ pEpInfo.EpDir = Direction? UsbEpDirIn : UsbEpDirOut;
+
+ if (State == TRUE) {
+ Status = UsbDeviceEpStall (UsbFuncIoDevPtr->DrvCore, (VOID*)(UINTN) &pEpInfo);
+ } else {
+ Status = UsbDeviceEpClearStall (UsbFuncIoDevPtr->DrvCore, (VOID*)(UINTN) &pEpInfo);
+ }
+
+ if (Status != EFI_SUCCESS) {
+ Status = 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ EventReg = (EventIndex->Event & DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK);
+ EventReg >>= DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS;
+ *EventFlag = FALSE;
+
+ //
+ // Assume default event size. Change it in switch case if
+ // different
+ //
+ *ProcessSize = 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_DEV_DISCONN_EVENT\n"));
+ *Message = EfiUsbMsgBusEventDetach;
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT:
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_USB_RESET_EVENT\n"));
+ //
+ // In resetDet will prepare setup Xfer package
+ //
+ UsbFuncIoDevPtr->DevReConnect = FALSE;
+ UsbFuncIoDevPtr->DevResetFlag = TRUE;
+
+ usbProcessDeviceResetDet (XdciCorePtr);
+ UsbDeviceSetAddress (UsbDeviceCorePtr, 0);
+ *Message = EfiUsbMsgBusEventReset;
+ *EventFlag = TRUE;
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT:
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_CONN_DONE_EVENT\n"));
+ usbProcessDeviceResetDone(XdciCorePtr);
+ UsbDeviceSetAddress(UsbDeviceCorePtr, 0);
+ UsbFuncIoDevPtr->DevReConnect = TRUE;
+ UsbFuncIoDevPtr->DevResetFlag = FALSE;
+ *EventFlag = TRUE;
+ *Message = EfiUsbMsgNone;
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT:
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_HBRNTN_REQ_EVENT\n"));
+ *Message = EfiUsbMsgBusEventSuspend;
+ *EventFlag = TRUE;
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT:
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_Device DWC_XDCI_EVENT_BUFF_DEV_WKUP_EVENT\n"));
+ *Message = EfiUsbMsgBusEventResume;
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_DEV_TST_LMP_RX_EVENT:
+ *ProcessSize = DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES;
+ *Message = EfiUsbMsgNone;
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFUDwcXdciProcessDeviceEvent: UNHANDLED 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_DEV_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_DEV_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_DEV_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_DEV_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_DEV_BUFF_OVFL_EVENT\n"));
+ break;
+
+ default:
+ *EventFlag = FALSE;
+ *Message = EfiUsbMsgNone;
+ DEBUG ((USB_FUIO_DEBUG_EVENT_I, "USBFUWcXdciProcessDeviceEvent: UNHANDLED 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ EpHandle = &XdciCorePtr->EpHandles[EndPointNum];
+ Trb = 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 = EFI_SUCCESS;
+ BufferLen = 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", (UINT32)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", (UINT32)Trb->BuffPtrLow));
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done Trb->BuffPtrHigh: %x!!!\n", (UINT32)Trb->BuffPtrHigh));
+
+ //
+ // Set CheckFlag to FALSE for 'DwcXdciEpRxData' function
+ // check the RX request complete and continue next transfer request
+ //
+ EpHandle->CheckFlag = FALSE;
+ EpHandle->CurrentXferRscIdx = 0;
+
+ DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D01!!\n"));
+ TrbCtrl = (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 = (Trb->LenXferParams & DWC_XDCI_TRB_STATUS_MASK) >> DWC_XDCI_TRB_STATUS_BIT_POS;
+
+ DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D03!!\n" ));
+ BufferLen = Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK;
+
+ DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D04 TrbCtrl :: %x!!\n", TrbCtrl));
+ switch (TrbCtrl) {
+ case DWC_XDCI_TRB_CTRL_TYPE_SETUP:
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Ep0 done DWC_XDCI_TRB_CTRL_TYPE_SETUP!!\n"));
+ //
+ // This is delay for other host USB controller(none Intel), identify device get fail issue.
+ //
+ gBS->Stall(130);
+ BufferLen = 8;
+
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "DWC_XDCI_TRB_CTRL_TYPE_SETUP!!\n"));
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "AlignedSetupBuffer::0x%08x!!\n", XdciCorePtr->AlignedSetupBuffer));
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Payload::0x%08x!!\n", (UINTN)Payload));
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "BufferLen::0x%08x!!\n", (UINTN)BufferLen));
+ *Message = EfiUsbMsgSetupPacket;
+ CopyMem (Payload, XdciCorePtr->AlignedSetupBuffer, BufferLen);
+
+ DEBUG ((USB_FUIO_DEBUG_EVENT_I, "Ep0 done D06!!\n"));
+ if (!(XdciCorePtr->AlignedSetupBuffer[0] & USB_SETUP_DATA_PHASE_DIRECTION_MASK)) {
+ if ((XdciCorePtr->AlignedSetupBuffer[0] == 0x00) ) {
+ if ((XdciCorePtr->AlignedSetupBuffer[1] == USB_DEV_SET_ADDRESS)) {
+ //
+ // set address
+ //
+ UsbSetAddress (
+ This,
+ (UINT32)(XdciCorePtr->AlignedSetupBuffer[3] << 8 | XdciCorePtr->AlignedSetupBuffer[2])
+ );
+
+ *Message = EfiUsbMsgNone;
+ } else if ((XdciCorePtr->AlignedSetupBuffer[1] == USB_DEV_SET_CONFIGURATION)) {
+ DEBUG ((USB_FUIO_DEBUG_EVENT_I, "\n set configure !!!"));
+ UsbSetconfigure (
+ This,
+ (UINT32)(XdciCorePtr->AlignedSetupBuffer[3] << 8 | XdciCorePtr->AlignedSetupBuffer[2])
+ );
+ *Message = 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) == 0) {
+ *Message = EfiUsbMsgEndpointStatusChangedRx;
+ } else {
+ *Message = EfiUsbMsgEndpointStatusChangedTx;
+ }
+ Payload->utr.EndpointIndex = (UINT8)(EndPointNum >> 1);
+ Payload->utr.Direction = (UINT8)(EndPointNum & 0x01);
+ Payload->utr.Buffer = (VOID*)(UINTN)(Trb->BuffPtrLow);
+
+ DEBUG ((DEBUG_INFO, "Ep0 EndPointNum: %x!!!\n", (UINT32)EndPointNum));
+ DEBUG ((DEBUG_INFO, "Ep0 done XferLength: %x!!!\n", (UINT32)UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferLength));
+ Payload->utr.Buffer = (VOID*)UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferAddress;
+ Payload->utr.BytesTransferred = UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferLength;
+
+ if (TrbSts == 0) {
+ if ((Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK) == 0) {
+ Payload->utr.TransferStatus = UsbTransferStatusComplete;
+ } else {
+ Payload->utr.TransferStatus = UsbTransferStatusActive;
+ }
+ } else if (TrbSts != 0) {
+ Trb->TrbCtrl |= DWC_XDCI_TRB_CTRL_HWO_MASK;
+ *Message = EfiUsbMsgNone;
+ Payload->utr.TransferStatus = UsbTransferStatusAborted;
+ DEBUG ((DEBUG_INFO, "Flush FIFO!!!\n" ));
+ EpInfo.EpNum = 0;
+ EpInfo.EpDir =UsbEpDirIn;
+ UsbXdciCoreFlushEpFifo(XdciCorePtr, &EpInfo);
+ EpInfo.EpNum = 0;
+ EpInfo.EpDir =UsbEpDirOut;
+ UsbXdciCoreFlushEpFifo(XdciCorePtr, &EpInfo);
+ DevStatus = UsbDeviceEp0RxSetup (UsbDeviceCorePtr, XdciCorePtr->AlignedSetupBuffer);
+ }
+
+ break;
+
+ case DWC_XDCI_TRB_CTRL_TYPE_STATUS2:
+ case DWC_XDCI_TRB_CTRL_TYPE_STATUS3:
+ Payload->utr.Buffer = (VOID*) UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferAddress;
+ Payload->utr.BytesTransferred = 0;
+ Payload->utr.EndpointIndex = (UINT8)(EndPointNum >> 1);
+ if ((EndPointNum & 0x01) == 0) {
+ *Message = EfiUsbMsgEndpointStatusChangedRx;
+ } else {
+ *Message = EfiUsbMsgEndpointStatusChangedTx;
+ }
+
+ if (TrbSts == 0) {
+ if ((Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK) == 0) {
+ Payload->utr.TransferStatus = UsbTransferStatusComplete;
+ } else {
+ Payload->utr.TransferStatus = UsbTransferStatusActive;
+ }
+ } else if (TrbSts != 0) {
+ Payload->utr.TransferStatus = UsbTransferStatusAborted;
+ }
+
+ DevStatus = UsbDeviceEp0RxSetup (UsbDeviceCorePtr, XdciCorePtr->AlignedSetupBuffer);
+
+ if (DevStatus) {
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: FAILED to queue SETUP\n"));
+ }
+ DEBUG ((DEBUG_INFO, "Status phase done. Queue next SETUP packet==>\n"));
+ break;
+
+ default:
+ *Message = 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ EpHandle = &XdciCorePtr->EpHandles[EndPointNum];
+ Trb = 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", (UINT32)Trb->TrbCtrl));
+
+ //
+ // Set CheckFlag to FALSE for 'DwcXdciEpRxData' function
+ // check the RX request complete and continue next transfer request
+ //
+ EpHandle->CheckFlag = FALSE;
+ EpHandle->CurrentXferRscIdx = 0;
+ *Message = EfiUsbMsgNone;
+
+ TrbCtrl = (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_TYPE_MASK) >> DWC_XDCI_TRB_CTRL_TYPE_BIT_POS;
+ TrbSts = (Trb->LenXferParams & DWC_XDCI_TRB_STATUS_MASK) >> DWC_XDCI_TRB_STATUS_BIT_POS;
+
+ Payload->utr.BytesTransferred = UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].XferLength;
+ Payload->utr.EndpointIndex = UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].LogEpNum;
+ Payload->utr.Direction = UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].Direction;
+ Payload->utr.Buffer = (VOID*)(UINTN)(Trb->BuffPtrLow);
+ UsbFuncIoDevPtr->EndPointXferRec[EndPointNum].Complete = TRUE;
+
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "EndPointAddress = 0x%08x\n", Payload->utr.EndpointIndex));
+ if (Payload->utr.Direction == EfiUsbEndpointDirectionDeviceTx) {
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Direction::EfiUsbEndpointDirectionDeviceTx\n"));
+ *Message = EfiUsbMsgEndpointStatusChangedTx;
+ } else {
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, " Direction::EfiUsbEndpointDirectionDeviceRx\n"));
+ *Message = EfiUsbMsgEndpointStatusChangedRx;
+ }
+
+ if (TrbSts == 0) {
+ if ((Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK) == 0) {
+ Payload->utr.TransferStatus = UsbTransferStatusComplete;
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::UsbTransferStatusComplete\n"));
+ } else {
+ Payload->utr.TransferStatus = UsbTransferStatusComplete;
+ Payload->utr.BytesTransferred -= (Trb->LenXferParams & DWC_XDCI_TRB_BUFF_SIZE_MASK);
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::UsbTransferStatusComplete\n"));
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "XferStatus::Length %d \n", Payload->utr.BytesTransferred ));
+ }
+ } else if (TrbSts != 0) {
+ Payload->utr.TransferStatus = 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 = USBFUIO_CONTEXT_FROM_PROTOCOL(This);
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+
+ *Message = 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 = USBFUIO_CONTEXT_FROM_PROTOCOL(This);
+
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ EventReg = EventIndex->Event;
+ *ProcessSize = DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES;
+ *EventFlag = TRUE;
+ TmpBufferSize = 0;
+
+ //
+ // Get EP num
+ //
+ EndPointNumber = (EventReg & DWC_XDCI_EVENT_BUFF_EP_NUM_MASK) >> DWC_XDCI_EVENT_BUFF_EP_NUM_BIT_POS;
+
+ EventStatus = EventReg & DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK;
+
+ //
+ // Interpret event and handle transfer completion here
+ //
+ EpEvent = (EventReg & DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK) >> DWC_XDCI_EVENT_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_XFER_CMPLT\n"));
+ if (EndPointNumber > 1) {
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP None_Control transfer\n"));
+ NoneEp0XferDone (This, EndPointNumber, Message, PayloadSize, Payload);
+ } 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_READY\n"));
+ *Message = EfiUsbMsgNone;
+ if(EndPointNumber < (sizeof(UsbFuncIoDevPtr->EndPointXferRec) / sizeof(UsbFuncIoDevPtr->EndPointXferRec[0]))) {
+ if ((UsbFuncIoDevPtr->EndPointXferRec[EndPointNumber].ZlpFlag == TRUE) && \
+ (UsbFuncIoDevPtr->EndPointXferRec[EndPointNumber].Complete == TRUE)) {
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "Request send ZLP\n"));
+ if ((EndPointNumber & 0x01) != 0) {
+ Transfer(This,
+ UsbFuncIoDevPtr->IndexPtrInEp.EndpointDesc->EndpointAddress,
+ EfiUsbEndpointDirectionDeviceTx,
+ &TmpBufferSize,
+ NULL
+ );
+ UsbFuncIoDevPtr->EndPointXferRec[EndPointNumber].ZlpFlag = FALSE;
+ }
+
+ }
+ } else {
+ //
+ // Is it data stage or status stage
+ //
+ // Data Statge
+ //
+ Ep_State = USB_EP_STATE_DATA;
+ //
+ // Control transfer
+ //
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "USBFU_EP Control transfer not ready\n"));
+ Ep0XferNotReady (This, EndPointNumber, Message, PayloadSize, Payload, EventStatus);
+ *EventFlag = FALSE;
+ }
+ break;
+
+ case DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS:
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "DWC_XDCI_EVENT_BUFF_EP_XFER_IN_PROGRESS\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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ CurrentEventAddr = (UINT32)(UINTN)(XdciCorePtr->CurrentEventBuffer);
+ EventReport = FALSE;
+ EpEventReport = FALSE;
+ ProceSsEventSize = 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", CurrentEventAddr));
+
+ while ((EventCount != 0) && (EventReport == FALSE)) {
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV::event0x%08x\n", XdciCorePtr->CurrentEventBuffer->Event));
+ if ((XdciCorePtr->CurrentEventBuffer->Event & DWC_XDCI_EVENT_DEV_MASK) != 0) {
+ //
+ // Device event
+ //
+ DeviceEventCheck (
+ This,
+ (USBD_EVENT_BUF*)(UINTN)CurrentEventAddr,
+ &ProceSsEventSize,
+ Message,
+ &EventReport
+ );
+ if (EventReport == TRUE) {
+ *EventFlag = TRUE;
+ }
+
+ } else {
+ //
+ // EndPoint Event
+ //
+ EpEventCheck (
+ This,
+ (USBD_EVENT_BUF*)(UINTN)CurrentEventAddr,
+ &ProceSsEventSize,
+ Message,
+ PayloadSize,
+ Payload,
+ &EpEventReport
+ );
+ }
+
+ if ((*Message != EfiUsbMsgNone) || (EpEventReport == TRUE)) {
+ EventReport = TRUE;
+ *EventFlag = TRUE;
+ }
+
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: CurrentEventAddr 0x%08x :: ProceSsEventSize 0x%08x\n", (UINTN)CurrentEventAddr,ProceSsEventSize));
+
+ EventCount -= ProceSsEventSize;
+ *ProceSsEvent += ProceSsEventSize;
+ if ((CurrentEventAddr + ProceSsEventSize) >= \
+ ((UINT32)(UINTN)(XdciCorePtr->AlignedEventBuffers) +
+ (sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))) {
+ CurrentEventAddr = (UINT32)(UINTN)(XdciCorePtr->AlignedEventBuffers);
+ } else {
+ CurrentEventAddr += ProceSsEventSize;
+ }
+ DEBUG ((USB_FUIO_DEBUG_EVENT_D, "FUEV:: CurrentEventAddr Update 0x%08x :: ProceSsEventSize 0x%08x\n", CurrentEventAddr,ProceSsEventSize));
+
+ XdciCorePtr->CurrentEventBuffer = (DWC_XDCI_EVENT_BUFFER*)(UINTN)CurrentEventAddr;
+ }
+
+ 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 instance.
+ @param[in] Message Indicates the event that initiated this
+ notification.
+ @param[in] PayloadSize On input, the size of the memory pointed by Payload.
+ On output, the amount of data returned in Payload.
+ @param[in] Payload A pointer to EFI_USBFN_MESSAGE_PAYLOAD instance to
+ return additional payload for current message.
+
+
+
+
+ @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 to
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ if (UsbFuncIoDevPtr->StartUpController == FALSE) {
+ UsbFnInitDevice (This);
+ }
+ OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ *Message = EfiUsbMsgNone;
+ MaxIntNum = (UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_GHWPARAMS1_REG) &
+ DWC_XDCI_GHWPARAMS1_NUM_INT_MASK) >>
+ DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS;
+
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ EventFlag = TRUE;
+
+ DEBUG ((USB_FUIO_DEBUG_EVENT_I, "XdciCorePtr->MaxDevIntLines 0x%08x\n", XdciCorePtr->MaxDevIntLines));
+ EventCount = UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG(0));
+
+ for (IntIndex = 0; IntIndex < XdciCorePtr->MaxDevIntLines ; IntIndex++) {
+ //
+ // Get the number of events HW has written for this
+ // interrupt line
+ //
+ EventCount = UsbRegRead ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG(IntIndex));
+ EventCount &= DWC_XDCI_EVNTCOUNT_MASK;
+ PeventCount = 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 from current
+ // event count
+ //
+ UsbRegWrite ((UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr, DWC_XDCI_EVNTCOUNT_REG(IntIndex), PeventCount);
+
+ //
+ // for debug
+ //
+ if (*Message != EfiUsbMsgNone) {
+ break;
+ }
+
+ if (EventFlag == 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 = NULL;
+ EFI_USB_ENDPOINT_COMPANION_DESCRIPTOR *EpCompDesc = NULL;
+
+ //
+ // start by clearing all data in the destination
+ //
+ SetMem (EpDest, sizeof(USB_EP_INFO), 0);
+ EpDesc = EpSrc->EndpointDesc;
+ EpCompDesc = EpSrc->EndpointCompDesc;
+
+ if (EpDesc != NULL) {
+ EpDest->EpNum = EpDesc->EndpointAddress & 0x0F; // Bits 0-3 are ep num
+ EpDest->EpDir = ((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 = EpDesc->Attributes & USB_ENDPOINT_TYPE_MASK;
+ EpDest->MaxPktSize = EpDesc->MaxPacketSize;
+ EpDest->Interval = EpDesc->Interval;
+ }
+ if (EpCompDesc != NULL) {
+ EpDest->MaxStreams = EpCompDesc->Attributes & USB_EP_BULK_BM_ATTR_MASK;
+ EpDest->BurstSize = EpCompDesc->MaxBurst;
+ EpDest->Mult = 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ Status = EFI_SUCCESS;
+ ReqPacket = 0;
+
+ switch (EndpointIndex) {
+ case 0: // Control endpoint
+ XfIoreq->EpInfo.EpNum = 0;
+ XfIoreq->EpInfo.EpDir = Direction? UsbEpDirIn : UsbEpDirOut;
+ break;
+
+
+ default:
+ if (Direction == 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 = *BufferSize/ XfIoreq->EpInfo.MaxPktSize;
+ ReqPacket = ((XfIoreq->XferLen % XfIoreq->EpInfo.MaxPktSize) == 0)? ReqPacket : ReqPacket + 1;
+ XfIoreq->XferLen = (UINT32)ReqPacket * XfIoreq->EpInfo.MaxPktSize;
+
+ }
+ break;
+ }
+
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ XfIoreq->XferBuffer = Buffer;
+ XfIoreq->XferLen = (UINT32)(*BufferSize);
+ XfIoreq->XferDone = NULL;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Primary function to handle transfer in either direction Based on specified
+ direction and on the specified endpoint.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @param[in] EndpointIndex Indicates the endpoint on which TX or RX transfer
+ needs to take place.
+ @param[in] Direction Direction of the endpoint.
+ @param[in] BufferSize If Direction is EfiUsbEndpointDirectionDeviceRx:
+ On input, the size of the Buffer in bytes.
+ On output, the amount of data returned in Buffer in bytes.
+ If Direction is EfiUsbEndpointDirectionDeviceTx:
+ On input, the size of the Buffer in bytes.
+ On output, the amount of data actually transmitted in bytes.
+ @param[in] Buffer If Direction is EfiUsbEndpointDirectionDeviceRx:
+ The Buffer to return the received data.
+ If Direction is EfiUsbEndpointDirectionDeviceTx:
+ The Buffer that contains the data to be transmitted.
+
+ @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 to
+ 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", EndpointIndex));
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "\n FU:Direction 0x%02x\n", Direction));
+
+ UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ UsbDeviceCorePtr = UsbFuncIoDevPtr->DrvCore;
+ XdciCorePtr = UsbDeviceCorePtr->ControllerHandle;
+ EndPoint = UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn : UsbEpDirOut);
+
+ Status = SetFnIoReqInfo (
+ This,
+ EndpointIndex,
+ Direction,
+ BufferSize,
+ Buffer,
+ &XferReq
+ );
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "Set SetFnIoReqInfo - Error Stop!!!\n"));
+ while(1);
+ Status = EFI_DEVICE_ERROR;
+ goto FUN_EXIT;
+ }
+
+ UsbFuncIoDevPtr->EndPointXferRec[EndPoint].EpNum = EndPoint;
+ UsbFuncIoDevPtr->EndPointXferRec[EndPoint].Direction = Direction;
+ UsbFuncIoDevPtr->EndPointXferRec[EndPoint].XferAddress = (UINTN)Buffer;
+ UsbFuncIoDevPtr->EndPointXferRec[EndPoint].XferLength = (UINT32)(*BufferSize);
+ UsbFuncIoDevPtr->EndPointXferRec[EndPoint].LogEpNum = EndpointIndex;
+ UsbFuncIoDevPtr->EndPointXferRec[EndPoint].Complete = FALSE;
+ UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag = FALSE;
+
+ Status = EFI_DEVICE_ERROR;
+ switch (EndpointIndex) {
+ case 0: // Control endpoint
+ if (*BufferSize == 0) {
+ if (Direction == EfiUsbEndpointDirectionDeviceTx) {
+ Status = UsbDeviceEp0TxStatus(UsbDeviceCorePtr);
+ } else {
+ Status = UsbDeviceEp0RxStatus(UsbDeviceCorePtr);
+ }
+ } else if (Direction == EfiUsbEndpointDirectionDeviceTx) {
+ Status = UsbXdciDeviceEpTxData(UsbDeviceCorePtr, &XferReq);
+ } else if (Direction == EfiUsbEndpointDirectionDeviceRx) {
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "\n Set Setup Package - ??? Stop!!!\n"));
+ }
+ break;
+
+ default:
+ Status = EFI_SUCCESS;
+ if (Direction == EfiUsbEndpointDirectionDeviceTx) {
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "\n EfiUsbEndpointDirectionDeviceTx Size = %d\n",(*BufferSize) ));
+ XferReq.Zlp = TRUE;
+ if ((((*BufferSize) % 512) == 0) && ((*BufferSize) != 0)) {
+ UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag = TRUE;
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "\n Set Zlp flag\n"));
+ }
+ Status = UsbXdciDeviceEpTxData (UsbDeviceCorePtr, &XferReq);
+ } else {
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "\n EfiUsbEndpointDirectionDeviceRx Size = %d\n",(*BufferSize) ));
+ Status = UsbXdciDeviceEpRxData (UsbDeviceCorePtr, &XferReq);
+ }
+ break;
+ }
+
+ if (EFI_ERROR(Status)) {
+ goto FUN_EXIT;
+ }
+
+ if (Status != EFI_SUCCESS) {
+ Status = 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 instance.
+
+ @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 = EFI_SUCCESS;
+ UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ if (UsbFuncIoDevPtr->StartUpController == TRUE) {
+ goto EXIT_START_CONTROLLER;
+ }
+
+ ConfigParams.ControllerId = USB_ID_DWC_XDCI;
+ ConfigParams.BaseAddress = (UINT32)UsbFuncIoDevPtr->XdciMmioBarAddr;
+ ConfigParams.Role = USB_ROLE_DEVICE;
+ ConfigParams.Speed = USB_SPEED_HIGH;
+
+ //
+ //*Vid = 0x8086
+ //*Pid = 0x0A65
+ //
+ UsbFuncIoDevPtr->VendorId = USBFU_VID;
+ UsbFuncIoDevPtr->DeviceId = USBFU_PID;
+ UsbFuncIoDevPtr->StartUpController = TRUE;
+
+ Status = UsbDeviceInit (&ConfigParams, &UsbFuncIoDevPtr->DrvCore);
+ if (Status != EFI_SUCCESS) {
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT_START_CONTROLLER;
+ }
+
+ UsbFuncIoDevPtr->XdciDrvIfHandle = UsbFuncIoDevPtr->DrvCore->ControllerHandle;
+
+EXIT_START_CONTROLLER:
+
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "StartXdciController - Exit :: %r\n", Status));
+ 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 instance.
+
+ @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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "StopController - Entry\n"));
+
+ if (UsbFuncIoDevPtr->StartUpController == FALSE) {
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "The Controller not yet start up skip deinit\n"));
+ return EFI_SUCCESS;
+ }
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DevStatus = UsbDeviceDeinit (UsbFuncIoDevPtr->DrvCore, TRUE);
+
+ UsbFuncIoDevPtr->DrvCore = NULL;
+ UsbFuncIoDevPtr->XdciDrvIfHandle = NULL;
+ UsbFuncIoDevPtr->StartUpController = FALSE;
+
+ if (DevStatus != 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-control endpoint.
+ Refer to the description for calling restrictions
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @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 that
+ 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 supported.
+
+**/
+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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ FlagPtr = NULL;
+
+ switch (PolicyType) {
+ case EfiUsbPolicyUndefined:
+ case EfiUsbPolicyMaxTransactionSize:
+ case EfiUsbPolicyZeroLengthTerminationSupport:
+
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ default:
+ FlagPtr = Buffer;
+ Status = EFI_SUCCESS;
+ break;
+ }
+
+ if (BufferSize < 1) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "SetEndpointPolicy - ERROR %r\n", Status));
+ return Status;
+ }
+
+ EndPoint = UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn : UsbEpDirOut);
+
+ UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag = *FlagPtr;
+
+ return Status;
+}
+
+
+/**
+ This function retrieves the configuration policy for the specified non-control
+ endpoint. There are no associated calling restrictions for this function.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @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 that
+ 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 supported.
+ @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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+ MaxPacketSize = 0;
+ SetFlag = FALSE;
+
+ switch (PolicyType) {
+ case EfiUsbPolicyUndefined:
+
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case EfiUsbPolicyMaxTransactionSize:
+ case EfiUsbPolicyZeroLengthTerminationSupport:
+ default:
+ if (Buffer == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+ break;
+ }
+
+ EndPoint = UsbGetPhysicalEpNum (EndpointIndex, Direction ? UsbEpDirIn : UsbEpDirOut);
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "GetEndpointPolicy - ERROR %r\n", Status));
+ return Status;
+ }
+
+ if (PolicyType == EfiUsbPolicyMaxTransactionSize) {
+
+ if (*BufferSize < sizeof(UINT32)) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ MaxPacketSize = MAX_TRANSFER_PACKET;
+ CopyMem (Buffer, &MaxPacketSize, sizeof(UINT32));
+ }
+
+ } else if (PolicyType == EfiUsbPolicyZeroLengthTerminationSupport) {
+ if (*BufferSize < sizeof(BOOLEAN)) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ SetFlag = TRUE;
+ CopyMem (Buffer, &SetFlag, sizeof(BOOLEAN));
+ }
+
+ } else if (PolicyType == EfiUsbPolicyZeroLengthTermination) {
+ if (*BufferSize < sizeof(BOOLEAN)) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ SetFlag = UsbFuncIoDevPtr->EndPointXferRec[EndPoint].ZlpFlag;
+ CopyMem (Buffer, &SetFlag, sizeof(BOOLEAN));
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+UsbFnInitDevice (
+ IN EFI_USBFN_IO_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ USB_XDCI_DEV_CONTEXT *UsbFuncIoDevPtr;
+
+ Status = EFI_SUCCESS;
+ UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ PlatformSpecificInit ();
+
+ UsbFuncIoDevPtr->StartUpController = FALSE;
+ Status = StartXdciController (&UsbFuncIoDevPtr->UsbFunIoProtocol);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto DEV_INIT_EXIT;
+ }
+
+ Status = UsbXdciDeviceConnect (UsbFuncIoDevPtr->DrvCore);
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbXdciDeviceConnect Status %x\n", Status));
+ if (Status != EFI_SUCCESS) {
+ Status = 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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ if (UsbFuncIoDevPtr->StartUpController == FALSE) {
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbFn:StopController:The Controller not yet start up force return EFI_SUCCESS\n"));
+ return EFI_SUCCESS;
+ }
+
+ //
+ // disconnect
+ //
+ Status = UsbDeviceDisconnect (UsbFuncIoDevPtr->DrvCore);
+ DEBUG ((USB_FUIO_DEBUG_LOAD, "UsbDeviceDisconnect Status %x\n", Status));
+ if (Status != EFI_SUCCESS) {
+ Status = EFI_DEVICE_ERROR;
+ goto DEV_DEINIT_EXIT;
+ }
+
+ //
+ // StopController
+ //
+ Status = StopXdciController (&UsbFuncIoDevPtr->UsbFunIoProtocol);
+ UsbFuncIoDevPtr->StartUpController = 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/UsbFuncIo.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFuncIo.h new file mode 100644 index 0000000000..711be0772f --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbFuncIo.h @@ -0,0 +1,234 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_USB_FUNCTION_IO_INTERFACE_H__
+#define __EFI_USB_FUNCTION_IO_INTERFACE_H__
+
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DriverLib.h>
+#include <Library/PcdLib.h>
+#include <Protocol/EfiUsbFnIo.h>
+#include <Library/PmicLib.h>
+#include <Library/UsbDeviceLib.h>
+#include <Library/PrintLib.h>
+#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/UsbIoNode.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIoNode.c new file mode 100644 index 0000000000..c51ced580f --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIoNode.c @@ -0,0 +1,177 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbDeviceDxe.h"
+
+
+/**
+ The SearchNode function search a memory address for record the driver allocate
+ memory region and the node to the head link list.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @param[in] Buffer The driver alocate memory address.
+ @param[out] Node The match node record of the driver aloocate
+ memory region.
+ @param[out] PNode The pervious match node record of the driver
+ 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 = USBFUIO_CONTEXT_FROM_PROTOCOL(This);
+ NodeL = UsbFuncIoDevPtr->FirstNodePtr;
+ PNodeL = NULL;
+ Status = EFI_NOT_FOUND;
+
+ while (Node != NULL) {
+ if (NodeL->AllocatePtr == Buffer) {
+ break;
+ }
+
+ PNodeL = NodeL;
+ NodeL = NodeL->NextPtr;
+ }
+
+ if (NodeL != NULL && Node != NULL) {
+ *Node = NodeL;
+ *PNode = PNodeL;
+ Status = 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 allocate
+ memory region and the node to the head link list.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @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 = USBFUIO_CONTEXT_FROM_PROTOCOL (This);
+
+ Status = SearchNode (This, Buffer, &Node, &PNode);
+
+ if (EFI_ERROR(Status) || PNode == NULL) {
+ DEBUG ((USB_DEBUG_MEM_NODE_ERROR, "RemoveNode - Node Not Found\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ if (Node != UsbFuncIoDevPtr->FirstNodePtr) {
+ PNode->NextPtr = Node->NextPtr;
+ } else {
+ UsbFuncIoDevPtr->FirstNodePtr = 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 driver allocate
+ memory region and insert the node to the head link list.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @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 == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ErrorExit;
+ }
+
+ UsbFuncIoDevPtr = USBFUIO_CONTEXT_FROM_PROTOCOL(This);
+
+ //
+ // Create the new node
+ //
+ NewNodePtr = AllocateZeroPool (sizeof(USB_MEM_NODE));
+ DEBUG ((USB_DEBUG_MEM_NODE_INFO, "NewNodePtr - Addr = 0x%08x\n",(UINTN)NewNodePtr));
+
+ if (NewNodePtr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ //
+ // insert the new node
+ //
+ CurrentNodePtr = UsbFuncIoDevPtr->FirstNodePtr;
+ UsbFuncIoDevPtr->FirstNodePtr = NewNodePtr;
+
+ if (CurrentNodePtr != NULL) {
+ NewNodePtr->NextPtr = CurrentNodePtr;
+ }
+
+ *Node = 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/UsbIoNode.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIoNode.h new file mode 100644 index 0000000000..0ff569bdd6 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/UsbIoNode.h @@ -0,0 +1,90 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_USB_FUIO_MEM_NODE__
+#define __EFI_USB_FUIO_MEM_NODE__
+
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DriverLib.h>
+
+#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 allocate
+ memory region and the node to the head link list.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @param[in] Buffer The driver alocate memory address.
+ @param[out] Node The match node record of the driver aloocate
+ memory region.
+ @param[out] PNode The pervious match node record of the driver
+ 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 allocate
+ memory region and the node to the head link list.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @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 driver allocate
+ memory region and insert the node to the head link list.
+
+ @param[in] This A pointer to the EFI_USBFN_IO_PROTOCOL instance.
+ @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/XdciCommon.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciCommon.h new file mode 100644 index 0000000000..468e8a83a5 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciCommon.h @@ -0,0 +1,156 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _XDCI_COMMON_H_
+#define _XDCI_COMMON_H_
+
+#define USB_SETUP_DATA_PHASE_DIRECTION_MASK (0x80)
+
+//
+// EP direction
+//
+typedef enum {
+ UsbEpDirOut = 0,
+ UsbEpDirIn = 1
+} USB_EP_DIR;
+
+//
+// USB Speeds
+//
+typedef enum {
+ USB_SPEED_HIGH = 0,
+ USB_SPEED_FULL,
+ USB_SPEED_LOW,
+ USB_SPEED_SUPER = 4
+} USB_SPEED;
+
+typedef enum {
+ USB_ID_DWC_XDCI = 0,
+ USB_CORE_ID_MAX
+} USB_CONTROLLER_ID;
+
+typedef enum {
+ USB_ROLE_HOST = 1,
+ USB_ROLE_DEVICE,
+ USB_ROLE_OTG
+} USB_ROLE;
+
+typedef enum {
+ USB_XFER_QUEUED = 0,
+ USB_XFER_SUCCESSFUL,
+ USB_XFER_STALL
+} USB_XFER_STATUS;
+
+typedef enum {
+ USB_DEVICE_DISCONNECT_EVENT = 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 = 7,
+ USB_DEVICE_ERRATIC_ERR_EVENT = 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 = 0,
+ U1,
+ U2,
+ U3,
+ SS_DIS,
+ RX_DET,
+ SS_INACT,
+ POLL,
+ RECOV,
+ HRESET,
+ CMPLY,
+ LPBK,
+ RESUME_RESET = 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 = 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 completion callback stage
+ UINT32 StreamId; // Stream ID. Only relevant for 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 callback
+ BOOLEAN Zlp; // Do zero-length transfer
+};
+
+#endif
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.c new file mode 100644 index 0000000000..47c5b80bd4 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.c @@ -0,0 +1,4033 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbDeviceMode.h"
+#include "XdciInterface.h"
+#include "XdciDWC.h"
+
+#pragma optimize ("", off)
+
+UINT32
+UsbRegRead (
+ IN UINT32 Base,
+ IN UINT32 Offset
+ )
+{
+ volatile UINT32 *addr = (volatile UINT32 *)(UINTN)(Base + Offset);
+ return *addr;
+}
+
+VOID
+UsbRegWrite (
+ IN UINT32 Base,
+ IN UINT32 Offset,
+ IN UINT32 val
+ )
+{
+ volatile UINT32 *addr = (volatile UINT32 *)(UINTN)(Base + Offset);
+ *addr = 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 == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (mps == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreGetCtrlMps: INVALID parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (CoreHandle->ActualSpeed) {
+ case USB_SPEED_HIGH:
+ *mps = DWC_XDCI_HS_CTRL_EP_MPS;
+ break;
+ case USB_SPEED_FULL:
+ *mps = DWC_XDCI_FS_CTRL_EP_MPS;
+ break;
+ case USB_SPEED_LOW:
+ *mps = DWC_XDCI_LS_CTRL_EP_MPS;
+ break;
+ case USB_SPEED_SUPER:
+ *mps = DWC_XDCI_SS_CTRL_EP_MPS;
+ break;
+ default:
+ *mps = 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 = EFI_SUCCESS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitEpCmdParams: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Reset params
+ //
+ EpCmdParams->Param0 = EpCmdParams->Param1 = EpCmdParams->Param2 = 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 = DWC_XDCI_PARAM1_SET_EP_CFG_STRM_CAP_MASK;
+ }
+
+ if (EpInfo->Interval) {
+ EpCmdParams->Param1 |= ((EpInfo->Interval-1) << DWC_XDCI_PARAM1_SET_EP_CFG_BINTM1_BIT_POS);
+ }
+
+ //
+ // Set EP num
+ //
+ EpCmdParams->Param1 |= (EpInfo->EpNum << DWC_XDCI_PARAM1_SET_EP_CFG_EP_NUM_BIT_POS);
+ //
+ // Set EP direction
+ //
+ EpCmdParams->Param1 |= (EpInfo->EpDir << DWC_XDCI_PARAM1_SET_EP_CFG_EP_DIR_BIT_POS);
+ //
+ // Set EP-specific Event enable for not ready and
+ // complete events
+ //
+ EpCmdParams->Param1 &= ~DWC_XDCI_PARAM1_SET_EP_CFG_EVT_EN_MASK;
+ //
+ // Setup the events we want enabled for this EP
+ //
+ EpCmdParams->Param1 |= (DWC_XDCI_PARAM1_SET_EP_CFG_EVT_XFER_NRDY_MASK |
+ 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 &= ~DWC_XDCI_PARAM1_SET_EP_CFG_INTR_NUM_MASK;
+
+ //
+ // Set FIFOnum = 0 for control EP0
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_MASK;
+
+ //
+ // Program FIFOnum for non-EP0 EPs
+ //
+ if (EpInfo->EpNum && EpInfo->EpDir) {
+ EpCmdParams->Param0 |= (EpInfo->EpNum << DWC_XDCI_PARAM0_SET_EP_CFG_FIFO_NUM_BIT_POS);
+ }
+
+ //
+ // Program max packet size
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_MPS_MASK;
+ EpCmdParams->Param0 |= (EpInfo->MaxPktSize << DWC_XDCI_PARAM0_SET_EP_CFG_MPS_BIT_POS);
+
+ //
+ // Set Burst size. 0 means burst size of 1
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_MASK;
+ EpCmdParams->Param0 |= (EpInfo->BurstSize << DWC_XDCI_PARAM0_SET_EP_CFG_BRST_SIZE_BIT_POS);
+
+ //
+ // Set EP type
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_MASK;
+ EpCmdParams->Param0 |= (EpInfo->EpType << DWC_XDCI_PARAM0_SET_EP_CFG_EP_TYPE_BIT_POS);
+
+ //
+ // Set config action
+ //
+ EpCmdParams->Param0 &= ~DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MASK;
+ EpCmdParams->Param0 |= (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 = 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 = 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 = 5000;//DWC_XDCI_MAX_DELAY_ITERATIONS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreIssueEpCmd: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = 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_EPCMD_CMD_ACTIVE_MASK))
+ break;
+ else
+ gBS->Stall (DWC_XDCI_MAX_DELAY_ITERATIONS);
+ } while (--MaxDelayIter);
+
+ if (!MaxDelayIter) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreIssueEpCmd. ERROR: Failed to issue Command\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 = DWC_XDCI_MAX_DELAY_ITERATIONS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushAllFifos: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = 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_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
+ );
+
+ //
+ // Wait until command completes
+ //
+ do {
+ if (!(UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_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 = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINT32 fifoNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushEpTxFifo: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = CoreHandle->BaseAddress;
+
+ //
+ // Translate to FIFOnum
+ // NOTE: Assuming this is a Tx EP
+ //
+ fifoNum = (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_PARAM_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_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
+ );
+
+
+ //
+ // Wait until command completes
+ //
+ do {
+ if (!(UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_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", Trb, BufferPtr, size));
+
+ Trb->BuffPtrLow = (UINT32)(UINTN)BufferPtr;
+ Trb->BuffPtrHigh = 0;
+ Trb->LenXferParams = size;
+ Trb->TrbCtrl = TrbCtrl << DWC_XDCI_TRB_CTRL_TYPE_BIT_POS;
+
+ if (ChainBit)
+ Trb->TrbCtrl |= ChainBit << DWC_XDCI_TRB_CTRL_CHAIN_BUFF_BIT_POS;
+
+ if (LastBit)
+ Trb->TrbCtrl |= LastBit << DWC_XDCI_TRB_CTRL_LST_TRB_BIT_POS;
+
+ Trb->TrbCtrl |= DWC_XDCI_TRB_CTRL_IOSP_MISOCH_MASK| DWC_XDCI_TRB_CTRL_HWO_MASK;
+
+ DEBUG ((DEBUG_INFO, "(DwcXdciCorePrepareOneTrb) Trb->BuffPtrLow = 0x%x, Trb->LenXferParams is 0x%x, Trb->TrbCtrl is 0x%x\n",
+ Trb->BuffPtrLow, Trb->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 == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitTrb: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Trb == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreInitTrb: INVALID handle\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Init TRB fields
+ // NOTE: Assuming we are only using 32-bit addresses
+ // TODO: update for 64-bit addresses
+ //
+ if (size <= DWC_XDCI_TRB_BUFF_SIZE_MASK) {
+ //
+ // Can transfer in one TRB
+ //
+ TrbCtrlChain = 0;
+ TrbCtrlLast = 1;
+ DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, BufferPtr, size);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Can't transfer in one TRB.
+ // Seperate it in every ONE_TRB_SIZE of TRB
+ //
+ TrbBuffer = BufferPtr;
+ TrbIndex = 0;
+ while (size > ONE_TRB_SIZE) {
+ TrbCtrlChain = 1;
+ TrbCtrlLast = 0;
+ DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, TrbBuffer, ONE_TRB_SIZE);
+ TrbBuffer += ONE_TRB_SIZE;
+ size -= ONE_TRB_SIZE;
+ Trb++;
+ TrbIndex++;
+ if (TrbIndex >= DWC_XDCI_TRB_NUM)
+ return EFI_OUT_OF_RESOURCES;
+ }
+ TrbCtrlChain = 0;
+ TrbCtrlLast = 1;
+ DwcXdciCorePrepareOneTrb (Trb, TrbCtrl, TrbCtrlLast, TrbCtrlChain, TrbBuffer, 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 = EFI_DEVICE_ERROR;
+ DWC_XDCI_TRB *Trb;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreStartEp0SetupXfer: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (CoreHandle->EpHandles[0].State == USB_EP_STATE_SETUP) {
+ DEBUG ((DEBUG_INFO, "EP0 was already in SETUP phase\n"));
+ return EFI_SUCCESS;
+ }
+
+ CoreHandle->EpHandles[0].State = USB_EP_STATE_SETUP;
+ Trb = CoreHandle->Trbs;
+ DEBUG ((DEBUG_INFO, "(DwcXdciCoreStartEp0SetupXfer)\n"));
+
+ status = DwcXdciCoreInitTrb (
+ CoreHandle,
+ Trb,
+ TRBCTL_SETUP,
+ CoreHandle->AlignedSetupBuffer,
+ 8
+ );
+
+ if (status)
+ return status;
+
+ //
+ // Issue a DEPSTRTXFER for EP0
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command to start transfer on physical
+ // endpoint 0
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ CoreHandle,
+ 0,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ //
+ // Save new resource index for this transfer
+ //
+ CoreHandle->EpHandles[0].CurrentXferRscIdx = ((UsbRegRead (
+ CoreHandle->BaseAddress,
+ 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 == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceStateChangeEvent: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CoreHandle->HirdVal = (Event & DWC_XDCI_EVENT_BUFF_DEV_HIRD_MASK) >> DWC_XDCI_EVENT_BUFF_DEV_HIRD_BIT_POS;
+
+ CoreHandle->LinkState = ((Event & DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_MASK) >> DWC_XDCI_EVENT_BUFF_DEV_LINK_STATE_BIT_POS);
+
+ if (CoreHandle->EventCallbacks.DevLinkStateCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.LinkState = CoreHandle->LinkState;
+ CoreHandle->EventCallbacks.CbEventParams.Hird = CoreHandle->HirdVal;
+ CoreHandle->EventCallbacks.CbEventParams.SsEvent = (Event & DWC_XDCI_EVENT_BUFF_DEV_SS_EVENT_MASK) ? 1 : 0;
+ CoreHandle->EventCallbacks.DevLinkStateCallback (&CoreHandle->EventCallbacks.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 == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciEndXfer: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ CoreHandle->EpHandles[EpNum].CheckFlag = FALSE;
+
+ //
+ // Issue a DEPENDXFER for EP
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ cmdParams = ((CoreHandle->EpHandles[EpNum].CurrentXferRscIdx << DWC_XDCI_EPCMD_RES_IDX_BIT_POS) | DWC_XDCI_EPCMD_FORCE_RM_MASK);
+
+ if (CoreHandle->EpHandles[EpNum].CurrentXferRscIdx == 0) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd(
+ CoreHandle,
+ EpNum,
+ cmdParams | DWC_XDCI_EPCMD_END_XFER,
+ &EpCmdParams
+ );
+
+ if (!status) {
+ CoreHandle->EpHandles[EpNum].CurrentXferRscIdx = 0;
+ TrbPtr = 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 = EFI_SUCCESS;
+
+ if (CoreHandle == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Flush all FIFOs
+ //
+ status = DwcXdciCoreFlushAllFifos(CoreHandle);
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDet: Failed to flush FIFOs\n"));
+ }
+
+ //
+ // Start SETUP phase on EP0
+ //
+ status = DwcXdciCoreStartEp0SetupXfer(CoreHandle);
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDet: Failed to start SETUP 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 = CoreHandle->ParentHandle;
+ status = 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 = EFI_SUCCESS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceResetDone: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = CoreHandle->BaseAddress;
+ CoreHandle->ActualSpeed = (UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG) & DWC_XDCI_DSTS_CONN_SPEED_MASK);
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceResetDone CoreHandle->ActualSpeed is %x\n", CoreHandle->ActualSpeed));
+
+ //
+ // Program MPS Based on the negotiated Speed
+ //
+ DwcXdciCoreGetCtrlMps (CoreHandle, &CoreHandle->EpHandles[0].EpInfo.MaxPktSize);
+ DwcXdciCoreGetCtrlMps (CoreHandle, &CoreHandle->EpHandles[1].EpInfo.MaxPktSize);
+
+ //
+ // Init DEPCFG cmd params for EP0
+ //
+ status = 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 = DwcXdciCoreIssueEpCmd (
+ CoreHandle,
+ 0,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ return status;
+ }
+
+ //
+ // Init DEPCFG cmd params for EP1
+ //
+ status = DwcXdciCoreInitEpCmdParams (
+ CoreHandle,
+ &CoreHandle->EpHandles[1].EpInfo,
+ DWC_XDCI_PARAM0_SET_EP_CFG_ACTN_MDFY_STATE,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ CoreHandle,
+ 1,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ //
+ // Put the other PHY into suspend
+ //
+ if (CoreHandle->ActualSpeed == USB_SPEED_SUPER) {
+ //
+ // Put HS PHY to suspend
+ //
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GUSB2PHYCFG_REG (0),
+ (UsbRegRead (BaseAddr, DWC_XDCI_GUSB2PHYCFG_REG(0)) | DWC_XDCI_GUSB2PHYCFG_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_GUSB3PIPECTL_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_GUSB3PIPECTL_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_GUSB2PHYCFG_SUSPEND_PHY_MASK)
+ );
+ }
+
+ //
+ // Notify upper layer if callback is registered
+ //
+ if (CoreHandle->EventCallbacks.DevResetDoneCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.Speed = CoreHandle->ActualSpeed;
+ CoreHandle->EventCallbacks.DevResetDoneCallback (&CoreHandle->EventCallbacks.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 == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessDeviceEvent: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Extract device event
+ //
+ event = (IntLineEventBuffer->Event & DWC_XDCI_EVENT_BUFF_DEV_EVT_MASK);
+ event >>= DWC_XDCI_EVENT_BUFF_DEV_EVT_BIT_POS;
+
+ //
+ // Assume default event size. Change it in switch case if
+ // different
+ //
+ *ProcessedEventSize = 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_EVENT\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_EVENT\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 = DWC_XDCI_DEV_EVENT_TST_LMP_SIZE_IN_BYTES;
+ break;
+
+ default:
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessDeviceEvent: UNHANDLED device event: %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 = USB_EP_STATE_SETUP;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEp0XferNotReady: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Is it data stage or status stage
+ //
+ if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_DATA_REQ_MASK) {
+ epState = USB_EP_STATE_DATA;
+ } else if (epEventStatus & DWC_XDCI_EVENT_BUFF_EP_CTRL_STATUS_REQ_MASK) {
+ epState = USB_EP_STATE_STATUS;
+ }
+
+ if ((EpNum == 0) && (epState == 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 = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.EpState = epState;
+ CoreHandle->EventCallbacks.DevXferNrdyCallback (&CoreHandle->EventCallbacks.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 = EFI_SUCCESS;
+ UINT32 TrbSts;
+ UINT32 TrbCtrl;
+ UINT32 TrbBufsize;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEp0XferPhaseDone: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ epHandle = &CoreHandle->EpHandles[EpNum];
+ Trb = CoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM);
+ DEBUG ((DEBUG_INFO, "(DwcXdciProcessEp0XferPhaseDone)EpNum is %d\n", EpNum));
+
+ if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone. HW owns TRB: %x!!!\n", (UINT32)(UINTN)Trb));
+ }
+
+ epHandle->CurrentXferRscIdx = 0;
+ epHandle->State = USB_EP_STATE_ENABLED;
+ TrbCtrl = (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_TYPE_MASK) >> DWC_XDCI_TRB_CTRL_TYPE_BIT_POS;
+ TrbSts = (Trb->LenXferParams & DWC_XDCI_TRB_STATUS_MASK) >> DWC_XDCI_TRB_STATUS_BIT_POS;
+ TrbBufsize = 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 = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.Buffer = CoreHandle->AlignedSetupBuffer;
+ status = CoreHandle->EventCallbacks.DevSetupPktReceivedCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+
+ if (!(CoreHandle->AlignedSetupBuffer[0] & USB_SETUP_DATA_PHASE_DIRECTION_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 = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.EpNum = (EpNum >> 1);
+ CoreHandle->EventCallbacks.CbEventParams.EpDir = (EpNum & 1);
+ CoreHandle->EventCallbacks.CbEventParams.Buffer = (UINT8 *)(UINTN)(Trb->BuffPtrLow);
+ CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCallbacks.CbEventParams);
+ }
+
+ //
+ // Status phase done. Queue next SETUP packet
+ //
+ status = DwcXdciCoreStartEp0SetupXfer(CoreHandle);
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessEp0XferPhaseDone: FAILED to queue SETUP\n"));
+ }
+ break;
+
+ case DWC_XDCI_TRB_CTRL_TYPE_DATA:
+ DEBUG ((DEBUG_INFO, "DATA\n"));
+ if (TrbSts == DWC_XDCI_TRB_STATUS_SETUP_PENDING || TrbBufsize != 0) {
+ DEBUG ((DEBUG_INFO, "ERROR: Control transfert aborted by host: Setup pending\n"));
+ DwcXdciCoreStartEp0SetupXfer (CoreHandle);
+ }
+
+ if (CoreHandle->EventCallbacks.DevXferDoneCallback) {
+ CoreHandle->EventCallbacks.CbEventParams.ParentHandle = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.EpNum = (EpNum >> 1);
+ CoreHandle->EventCallbacks.CbEventParams.EpDir = (EpNum & 1);
+ CoreHandle->EventCallbacks.CbEventParams.Buffer = (UINT8 *)(UINTN)(Trb->BuffPtrLow);
+ CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCallbacks.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 == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ epHandle = &CoreHandle->EpHandles[EpNum];
+ epHandle->CurrentXferRscIdx = 0;
+ Trb = epHandle->Trb;
+ XferReq = &epHandle->XferHandle;
+
+ //
+ // if transfer done, set CheckFlag to FALSE for allow next transfer request.
+ //
+ epHandle->CheckFlag = FALSE;
+
+ if ((Trb == NULL) || (XferReq == NULL)) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpXferDone: INVALID parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Compute the actual transfer length
+ //
+ XferReq->ActualXferLen = XferReq->XferLen;
+ remainingLen = (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 -= 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 = CoreHandle->ParentHandle;
+ CoreHandle->EventCallbacks.CbEventParams.EpNum = (EpNum >> 1);
+ CoreHandle->EventCallbacks.CbEventParams.EpDir = (EpNum & 1);
+ CoreHandle->EventCallbacks.CbEventParams.EpType = epHandle->EpInfo.EpType;
+ CoreHandle->EventCallbacks.CbEventParams.Buffer = (UINT8 *)(UINTN)(epHandle->Trb->BuffPtrLow);
+ CoreHandle->EventCallbacks.DevXferDoneCallback (&CoreHandle->EventCallbacks.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 == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessEpEvent: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ epEvent = IntLineEventBuffer->Event;
+
+ *ProcessedEventSize = DWC_XDCI_DEV_EVENT_DEFAULT_SIZE_IN_BYTES;
+
+ //
+ // Get EP num
+ //
+ EpNum = ((epEvent & DWC_XDCI_EVENT_BUFF_EP_NUM_MASK) >> DWC_XDCI_EVENT_BUFF_EP_NUM_BIT_POS);
+ epEventStatus = (epEvent & DWC_XDCI_EVENT_BUFF_EP_EVENT_STATUS_MASK);
+
+ //
+ // Interpret event and handle transfer completion here
+ //
+ epEvent = ((epEvent & DWC_XDCI_EVENT_BUFF_EP_EVENT_MASK) >> DWC_XDCI_EVENT_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 = 0;
+ UINT32 currentEventAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessInterruptLineEvents: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (CoreHandle->CurrentEventBuffer == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciProcessInterruptLineEvents: INVALID event Buffer\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ currentEventAddr = (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 -= ProcessedEventSize;
+ *ProcessedEventCount += ProcessedEventSize;
+ if ((currentEventAddr + ProcessedEventSize) >=
+ ((UINT32)(UINTN)(CoreHandle->AlignedEventBuffers) + (sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))
+ ) {
+ currentEventAddr = (UINT32)(UINTN)(CoreHandle->AlignedEventBuffers);
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessInterruptLineEvents: Event Buffer bound reached\n"));
+ } else {
+ currentEventAddr += ProcessedEventSize;
+ }
+
+ CoreHandle->CurrentEventBuffer = (DWC_XDCI_EVENT_BUFFER *)(UINTN)currentEventAddr;
+ }
+
+ 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 = EFI_DEVICE_ERROR;
+ UINT32 BaseAddr;
+ XDCI_CORE_HANDLE *LocalCoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINT8 i;
+
+ LocalCoreHandle = (XDCI_CORE_HANDLE *)AllocateZeroPool (sizeof(XDCI_CORE_HANDLE));
+
+ if (CoreHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (LocalCoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to allocate handle for xDCI\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (LocalCoreHandle, sizeof(XDCI_CORE_HANDLE));
+
+ LocalCoreHandle->ParentHandle = deviceCorePtr;
+
+ *CoreHandle = (VOID *)LocalCoreHandle;
+
+ LocalCoreHandle->Id = ConfigParams->ControllerId;
+ LocalCoreHandle->BaseAddress = BaseAddr = ConfigParams->BaseAddress;
+ LocalCoreHandle->Flags = ConfigParams->Flags;
+ LocalCoreHandle->DesiredSpeed = LocalCoreHandle->ActualSpeed = ConfigParams->Speed;
+ LocalCoreHandle->Role = 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 = 0;
+ LocalCoreHandle->EpHandles[0].EpInfo.EpDir = UsbEpDirOut;
+ LocalCoreHandle->EpHandles[0].EpInfo.EpType = USB_ENDPOINT_CONTROL;
+ LocalCoreHandle->EpHandles[0].EpInfo.MaxPktSize = DWC_XDCI_SS_CTRL_EP_MPS;
+ //
+ // 0 means burst size of 1
+ //
+ LocalCoreHandle->EpHandles[0].EpInfo.BurstSize = 0;
+
+ LocalCoreHandle->EpHandles[1].EpInfo.EpNum = 0;
+ LocalCoreHandle->EpHandles[1].EpInfo.EpDir = UsbEpDirIn;
+ LocalCoreHandle->EpHandles[1].EpInfo.EpType = USB_ENDPOINT_CONTROL;
+ LocalCoreHandle->EpHandles[1].EpInfo.MaxPktSize = DWC_XDCI_SS_CTRL_EP_MPS;
+ //
+ // 0 means burst size of 1
+ //
+ LocalCoreHandle->EpHandles[1].EpInfo.BurstSize = 0;
+
+ LocalCoreHandle->DevState = 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 (BaseAddr, 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_GUSB2PHYCFG_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 = 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 = ((UsbRegRead (BaseAddr, DWC_XDCI_GHWPARAMS1_REG) &
+ DWC_XDCI_GHWPARAMS1_NUM_INT_MASK) >>
+ DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS);
+
+ DEBUG ((DEBUG_INFO, "Max dev int lines: %d\n", LocalCoreHandle->MaxDevIntLines));
+ //
+ // 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 = (DWC_XDCI_EVENT_BUFFER *)
+ ((UINT32)(UINTN)(LocalCoreHandle->EventBuffers) +
+ ((sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) -
+ (((UINT32)(UINTN)(LocalCoreHandle->EventBuffers)) %
+ (sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))));
+
+ for (i = 0; i < LocalCoreHandle->MaxDevIntLines; i++) {
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GEVNTADR_REG (i),
+ (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers + i * sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)
+ );
+
+ //
+ // Clear High 32bit address register, GEVNTADR register is 64-bit register
+ // default is 0xffffffffffffffff
+ //
+ UsbRegWrite (BaseAddr, DWC_XDCI_GEVNTADR_REG (i) + 4, 0x00000000);
+
+ LocalCoreHandle->CurrentEventBuffer = LocalCoreHandle->AlignedEventBuffers;
+ //
+ // 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, Count: %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_RAMCLKSEL_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", UsbRegRead (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", UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", UsbRegRead (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_GUSB2PHYCFG_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_GUSB3PIPECTL_SUSPEND_PHY_MASK)
+ );
+
+ //
+ // Issue DEPSTARTCFG command for EP0
+ //
+ status = 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 = 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 = 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 = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams);
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP0\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPCFG command for EP1
+ //
+ status = 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 = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP1\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPXFERCFG command for EP0
+ //
+ status = 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 = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPXFERCFG command for EP1
+ //
+ status = 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 = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1\n"));
+ return status;
+ }
+
+ //
+ // Prepare a Buffer for SETUP packet
+ //
+ LocalCoreHandle->Trbs = (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 = LocalCoreHandle->DefaultSetupBuffer +
+ (DWC_XDCI_SETUP_BUFF_SIZE -
+ ((UINT32)(UINTN)(LocalCoreHandle->DefaultSetupBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
+
+ //
+ // Aligned Buffer for status phase
+ //
+ LocalCoreHandle->AlignedMiscBuffer = LocalCoreHandle->MiscBuffer +
+ (DWC_XDCI_SETUP_BUFF_SIZE -
+ ((UINT32)(UINTN)(LocalCoreHandle->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 = (XDCI_CORE_HANDLE *)CoreHandle;
+
+ if (LocalCoreHandle == 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 = CallbackFunc;
+ break;
+
+ case USB_DEVICE_RESET_EVENT:
+ LocalCoreHandle->EventCallbacks.DevBusResetCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_CONNECTION_DONE:
+ LocalCoreHandle->EventCallbacks.DevResetDoneCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_STATE_CHANGE_EVENT:
+ LocalCoreHandle->EventCallbacks.DevLinkStateCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_WAKEUP_EVENT:
+ LocalCoreHandle->EventCallbacks.DevWakeupCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_HIBERNATION_REQ_EVENT:
+ LocalCoreHandle->EventCallbacks.DevHibernationCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_SOF_EVENT:
+ LocalCoreHandle->EventCallbacks.DevSofCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_ERRATIC_ERR_EVENT:
+ LocalCoreHandle->EventCallbacks.DevErraticErrCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_CMD_CMPLT_EVENT:
+ LocalCoreHandle->EventCallbacks.DevCmdCmpltCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_BUFF_OVERFLOW_EVENT:
+ LocalCoreHandle->EventCallbacks.DevBuffOvflwCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_TEST_LMP_RX_EVENT:
+ LocalCoreHandle->EventCallbacks.DevTestLmpRxCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_SETUP_PKT_RECEIVED:
+ LocalCoreHandle->EventCallbacks.DevSetupPktReceivedCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_XFER_NRDY:
+ LocalCoreHandle->EventCallbacks.DevXferNrdyCallback = CallbackFunc;
+ break;
+
+ case USB_DEVICE_XFER_DONE:
+ LocalCoreHandle->EventCallbacks.DevXferDoneCallback = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+
+ if (LocalCoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreUnregisterCallback: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ switch (event) {
+ case USB_DEVICE_DISCONNECT_EVENT:
+ LocalCoreHandle->EventCallbacks.DevDisconnectCallback = NULL;
+ break;
+
+ case USB_DEVICE_RESET_EVENT:
+ LocalCoreHandle->EventCallbacks.DevBusResetCallback = NULL;
+ break;
+
+ case USB_DEVICE_CONNECTION_DONE:
+ LocalCoreHandle->EventCallbacks.DevResetDoneCallback = NULL;
+ break;
+
+ case USB_DEVICE_STATE_CHANGE_EVENT:
+ LocalCoreHandle->EventCallbacks.DevLinkStateCallback = NULL;
+ break;
+
+ case USB_DEVICE_WAKEUP_EVENT:
+ LocalCoreHandle->EventCallbacks.DevWakeupCallback = NULL;
+ break;
+
+ case USB_DEVICE_HIBERNATION_REQ_EVENT:
+ LocalCoreHandle->EventCallbacks.DevHibernationCallback = NULL;
+ break;
+
+ case USB_DEVICE_SOF_EVENT:
+ LocalCoreHandle->EventCallbacks.DevSofCallback = NULL;
+ break;
+
+ case USB_DEVICE_ERRATIC_ERR_EVENT:
+ LocalCoreHandle->EventCallbacks.DevErraticErrCallback = NULL;
+ break;
+
+ case USB_DEVICE_CMD_CMPLT_EVENT:
+ LocalCoreHandle->EventCallbacks.DevCmdCmpltCallback = NULL;
+ break;
+
+ case USB_DEVICE_BUFF_OVERFLOW_EVENT:
+ LocalCoreHandle->EventCallbacks.DevBuffOvflwCallback = NULL;
+ break;
+
+ case USB_DEVICE_TEST_LMP_RX_EVENT:
+ LocalCoreHandle->EventCallbacks.DevTestLmpRxCallback = NULL;
+ break;
+
+ case USB_DEVICE_SETUP_PKT_RECEIVED:
+ LocalCoreHandle->EventCallbacks.DevSetupPktReceivedCallback = NULL;
+ break;
+
+ case USB_DEVICE_XFER_NRDY:
+ LocalCoreHandle->EventCallbacks.DevXferNrdyCallback = NULL;
+ break;
+
+ case USB_DEVICE_XFER_DONE:
+ LocalCoreHandle->EventCallbacks.DevXferDoneCallback = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 BaseAddr;
+ UINT32 eventCount;
+ UINT32 ProcessedEventCount;
+ UINT32 i;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreIsrRoutine: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (LocalCoreHandle->InterrupProcessing == TRUE) {
+ DEBUG ((DEBUG_INFO, "interrupProcessing.........\n"));
+ return EFI_SUCCESS;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+ //
+ // Event Buffer corresponding to each interrupt line needs
+ // to be Processed
+ //
+ LocalCoreHandle->InterrupProcessing = TRUE;
+ for (i = 0; i < LocalCoreHandle->MaxDevIntLines; i++) {
+ //
+ // Get the number of events HW has written for this
+ // interrupt line
+ //
+ eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i));
+ eventCount &= DWC_XDCI_EVNTCOUNT_MASK;
+ ProcessedEventCount = 0;
+
+ //
+ // Process interrupt line Buffer only if count is non-zero
+ //
+ if (eventCount) {
+ //
+ // Process events in this Buffer
+ //
+ DwcXdciProcessInterruptLineEvents (LocalCoreHandle, eventCount, &ProcessedEventCount);
+ //
+ // Write back the Processed number of events so HW decrements it from current
+ // event count
+ //
+ UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (i), ProcessedEventCount);
+ }
+ }
+ LocalCoreHandle->InterrupProcessing = FALSE;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Interface:
+ This function is used as an interrupt service routine and it processes only one event at a time.
+ @CoreHandle: xDCI controller handle
+
+**/
+EFI_STATUS
+EFIAPI
+DwcXdciCoreIsrRoutineTimerBased (
+ IN VOID *CoreHandle
+ )
+{
+ XDCI_CORE_HANDLE *LocalCoreHandle = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 BaseAddr;
+ UINT32 eventCount;
+ UINT32 ProcessedEventCount;
+ UINT32 currentEventAddr;
+ UINT32 ProcessedEventSize = 0;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreIsrRoutineTimerBased: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (LocalCoreHandle->CurrentEventBuffer == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreIsrRoutineTimerBased: INVALID event Buffer\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0)) & DWC_XDCI_EVNTCOUNT_MASK;
+
+ if (LocalCoreHandle->InterrupProcessing == TRUE) {
+ DEBUG ((DEBUG_INFO, "interrupProcessing.........\n"));
+ return EFI_SUCCESS;
+ }
+
+ LocalCoreHandle->InterrupProcessing = TRUE;
+
+ ProcessedEventCount = 0;
+ currentEventAddr = (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 -= ProcessedEventSize;
+ ProcessedEventCount += ProcessedEventSize;
+ if ((currentEventAddr + ProcessedEventSize) >=
+ ((UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers) + (sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))
+ ) {
+ currentEventAddr = (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers);
+ DEBUG ((DEBUG_INFO, "DwcXdciProcessInterruptLineEvents: Event Buffer bound reached\n"));
+ } else {
+ currentEventAddr += ProcessedEventSize;
+ }
+
+ LocalCoreHandle->CurrentEventBuffer = (DWC_XDCI_EVENT_BUFFER *)(UINTN)currentEventAddr;
+ UsbRegWrite (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0), ProcessedEventCount);
+ LocalCoreHandle->InterrupProcessing = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINT32 BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreConnect: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = 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_CTRL_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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINT32 BaseAddr;
+ UINT32 eventCount;
+ UINT32 dsts;
+ UINT32 i;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0));
+ eventCount &= DWC_XDCI_EVNTCOUNT_MASK;
+
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: eventCount=%d\n", eventCount));
+ while (eventCount) {
+ DwcXdciCoreIsrRoutine(LocalCoreHandle);
+ eventCount = UsbRegRead (BaseAddr, DWC_XDCI_EVNTCOUNT_REG (0));
+ eventCount &= DWC_XDCI_EVNTCOUNT_MASK;
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: eventCount=%d\n", eventCount));
+ }
+
+ //
+ // Issue DEPENDXFER for active transfers
+ //
+ for (i = 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 = UsbRegRead (BaseAddr, DWC_XDCI_DSTS_REG);
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreDisconnect: waiting halt: DSTS=0x%x\n", dsts));
+ if ((dsts & DWC_XDCI_DSTS_DEV_CTRL_HALTED_MASK) != 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreGetSpeed: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Speed == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreGetSpeed: INVALID parameter\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Speed = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreSetAddress: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = 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 = UsbDevStateAddress;
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_GCTL_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_GCTL_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DEVTEN_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DEVTEN_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DCFG_REG: 0x%x\n", UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", UsbRegRead (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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS status;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreSetConfig: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Issue DEPSTARTCFG command on EP0 (new config for
+ // non-control EPs)
+ //
+ status = 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 EPCMD_START_NEW_CONFIG command\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ (EPCMD_START_NEW_CONFIG | (2 << DWC_XDCI_EPCMD_RES_IDX_BIT_POS)),
+ &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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciSetLinkState: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = 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_STATE_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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS status;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciInitEp: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+
+ //
+ // Save EP properties
+ //
+ CopyMem (&(LocalCoreHandle->EpHandles[EpNum].EpInfo), EpInfo, sizeof (USB_EP_INFO));
+
+ //
+ // Init CheckFlag
+ //
+ LocalCoreHandle->EpHandles[EpNum].CheckFlag = FALSE;
+
+ //
+ // Init DEPCFG cmd params for EP
+ //
+ status = 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_SET_EP_CONFIG command\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ CoreHandle,
+ EpNum,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciInitEp: Failed to issue EPCMD_SET_EP_CONFIG command\n"));
+ return status;
+ }
+
+ //
+ // Issue a DEPXFERCFG command for endpoint
+ //
+ status = 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_SET_EP_XFER_RES_CONFIG command\n"));
+ return status;
+ }
+
+ //
+ // Issue the command
+ //
+ status = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 EpNum;
+ UINT32 BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpEnable: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 EpNum;
+ UINT32 BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpDisable: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS status;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpStall: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+
+ //
+ // Set Ep State Info
+ //
+ if (LocalCoreHandle->EpHandles[EpNum].State != USB_EP_STATE_STALLED) {
+ LocalCoreHandle->EpHandles[EpNum].OrgState = LocalCoreHandle->EpHandles[EpNum].State;
+ LocalCoreHandle->EpHandles[EpNum].State = USB_EP_STATE_STALLED;
+ }
+ //
+ // Issue a DWC_XDCI_EPCMD_SET_STALL for EP
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Issue the command
+ //
+ status = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS status;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpClearStall: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+
+ //
+ // Set Ep State Info
+ //
+ LocalCoreHandle->EpHandles[EpNum].State = LocalCoreHandle->EpHandles[EpNum].OrgState;
+
+ //
+ // Issue a DWC_XDCI_EPCMD_CLEAR_STALL for EP
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Issue the command
+ //
+ status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ EpNum,
+ DWC_XDCI_EPCMD_CLEAR_STALL,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpStall: Failed to issue EP clea stall command\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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ UINT32 EpNum;
+ UINT32 BaseAddr;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpSetNrdy: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = 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_ACTIVE_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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+ DWC_XDCI_TRB *Trb;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveSetupPkt: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ LocalCoreHandle->EpHandles[0].EpInfo.EpNum = 0;
+ LocalCoreHandle->EpHandles[0].EpInfo.EpDir = 0;
+ LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_SETUP;
+ Trb = LocalCoreHandle->Trbs;
+ DEBUG ((DEBUG_INFO, "(DwcXdciEp0ReceiveSetupPkt)\n"));
+
+ Status = 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 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "\nDwcXdciEp0ReceiveSetupPkt: Failed to issue Start Transfer command"));
+ }
+
+ //
+ // Save new resource index for this transfer
+ //
+ LocalCoreHandle->EpHandles[0].CurrentXferRscIdx = ((UsbRegRead(LocalCoreHandle->BaseAddress, DWC_XDCI_EPCMD_REG(0)) &
+ DWC_XDCI_EPCMD_RES_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 = (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 == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveStatusPkt: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // We are receiving on EP0 so physical EP is 0
+ //
+ Trb = 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 = 0;
+ LocalCoreHandle->EpHandles[0].EpInfo.EpDir = 0;
+
+ //
+ // OUT data phase for 3-phased control transfer
+ //
+ TrbCtrl = TRBCTL_3_PHASE;
+
+ //
+ // Init TRB for the transfer
+ //
+ Status = DwcXdciCoreInitTrb (
+ LocalCoreHandle,
+ Trb,
+ TrbCtrl,
+ LocalCoreHandle->AlignedSetupBuffer,
+ 0
+ );
+
+ if (!Status) {
+ //
+ // Issue a DEPSTRTXFER for EP0
+ // Reset params
+ //
+ EpCmdParams.Param0 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0ReceiveStatusPkt: Failed to issue Start Transfer command for EP0\n"));
+ }
+ //
+ // Save new resource index for this transfer
+ //
+ LocalCoreHandle->EpHandles[0].CurrentXferRscIdx = ((UsbRegRead(BaseAddr, DWC_XDCI_EPCMD_REG(0)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_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 = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_TRB *Trb;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ EFI_STATUS Status;
+ UINT32 BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // We are sending on EP0 so physical EP is 1
+ //
+ Trb = (LocalCoreHandle->Trbs + (1 * DWC_XDCI_TRB_NUM));
+ DEBUG ((DEBUG_INFO, "(DwcXdciEp0SendStatusPkt)\n"));
+
+ LocalCoreHandle->EpHandles[0].State = USB_EP_STATE_STATUS;
+ Status = 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 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEp0SendStatusPkt: Failed to issue Start Transfer on EP0\n"));
+ }
+
+ //
+ // Save new resource index for this transfer
+ //
+ LocalCoreHandle->EpHandles[1].CurrentXferRscIdx = ((UsbRegRead(BaseAddr, DWC_XDCI_EPCMD_REG(1)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
+ LocalCoreHandle->EpHandles[0].State = 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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ DWC_XDCI_TRB *Trb;
+ DWC_XDCI_TRB_CONTROL TrbCtrl;
+ EFI_STATUS Status;
+ UINT32 EpNum;
+ UINT32 BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (XferReq == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: INVALID transfer request\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (
+ XferReq->EpInfo.EpNum,
+ XferReq->EpInfo.EpDir
+ );
+
+ Trb = (LocalCoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM));
+ DEBUG ((DEBUG_INFO, "(DwcXdciEpTxData)EpNum is %d\n", EpNum));
+
+
+ if (EpNum > 1)
+ TrbCtrl = TRBCTL_NORMAL;
+ else
+ TrbCtrl = TRBCTL_CTRL_DATA_PHASE;
+
+ if (Trb->TrbCtrl & DWC_XDCI_TRB_CTRL_HWO_MASK) {
+ Status = DwcXdciEndXfer (LocalCoreHandle, EpNum);
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: Failed to end previous transfer\n"));
+ }
+
+ Status = DwcXdciCoreFlushEpTxFifo (LocalCoreHandle, EpNum);
+ if (Status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpTxData: Failed to end previous transfer\n"));
+ }
+ }
+
+ //
+ // Data phase
+ //
+ CopyMem (&(LocalCoreHandle->EpHandles[EpNum].XferHandle), XferReq, sizeof (USB_XFER_REQUEST));
+ LocalCoreHandle->EpHandles[EpNum].State = USB_EP_STATE_DATA;
+
+ LocalCoreHandle->EpHandles[EpNum].Trb = Trb;
+
+ Status = 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 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ EpNum,
+ EPCMD_START_XFER,
+ &EpCmdParams
+ );
+
+ //
+ // Save new resource index for this transfer
+ //
+ LocalCoreHandle->EpHandles[EpNum].CurrentXferRscIdx = ((UsbRegRead (BaseAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_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 = (XDCI_CORE_HANDLE *)CoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ DWC_XDCI_TRB *Trb;
+ DWC_XDCI_TRB_CONTROL TrbCtrl;
+ EFI_STATUS Status;
+ UINT32 EpNum;
+ UINT32 BaseAddr;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (XferReq == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpRxData: INVALID transfer request\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BaseAddr = LocalCoreHandle->BaseAddress;
+
+ //
+ // Convert to physical endpoint
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (XferReq->EpInfo.EpNum, XferReq->EpInfo.EpDir);
+
+ Trb = (LocalCoreHandle->Trbs + (EpNum * DWC_XDCI_TRB_NUM));
+ DEBUG ((DEBUG_INFO, "(DwcXdciEpRxData)EpNum is %d\n", EpNum));
+
+ if (EpNum > 1)
+ TrbCtrl = TRBCTL_NORMAL;
+ else
+ TrbCtrl = 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 == TRUE) {
+ return EFI_NOT_READY;
+ }
+
+ LocalCoreHandle->EpHandles[EpNum].CheckFlag = TRUE;
+
+ //
+ // Data phase
+ //
+ CopyMem (&(LocalCoreHandle->EpHandles[EpNum].XferHandle), XferReq, sizeof (USB_XFER_REQUEST));
+
+ LocalCoreHandle->EpHandles[EpNum].State = USB_EP_STATE_DATA;
+
+ LocalCoreHandle->EpHandles[EpNum].Trb = Trb;
+
+ DEBUG ((DEBUG_INFO, "(DwcXdciEpRxData)XferReq->XferLen is 0x%x\n", XferReq->XferLen));
+
+ Status = 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 = EpCmdParams.Param1 = EpCmdParams.Param2 = 0;
+
+ //
+ // Init the lower re-bits for TRB address
+ //
+ EpCmdParams.Param1 = (UINT32)(UINTN)Trb;
+
+ //
+ // Issue the command
+ //
+ Status = 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 = ((UsbRegRead(BaseAddr, DWC_XDCI_EPCMD_REG(EpNum)) & DWC_XDCI_EPCMD_RES_IDX_MASK) >> DWC_XDCI_EPCMD_RES_IDX_BIT_POS);
+
+ return Status;
+}
+
+
+
+STATIC
+EFI_STATUS
+DwcXdciCoreFlushEpFifo (
+ IN XDCI_CORE_HANDLE *CoreHandle,
+ IN UINT32 EpNum
+ )
+{
+ UINT32 BaseAddr;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINT32 fifoNum;
+ UINT32 Param;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "ERROR: DwcXdciCoreFlushEpTxFifo: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ BaseAddr = CoreHandle->BaseAddress;
+
+ //
+ // Translate to FIFOnum
+ // NOTE: Assuming this is a Tx EP
+ //
+ fifoNum = (EpNum >> 1);
+
+ //
+ // TODO: Currently we are only using TxFIFO 0. Later map these
+ // Write the FIFO num/dir param for the generic command.
+ //
+
+ Param = UsbRegRead (BaseAddr, DWC_XDCI_DGCMD_PARAM_REG);
+ Param &= ~(DWC_XDCI_DGCMD_PARAM_TX_FIFO_NUM_MASK | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK);
+
+ if ((EpNum & 0x01) != 0) {
+ Param |= (fifoNum | DWC_XDCI_DGCMD_PARAM_TX_FIFO_DIR_MASK);
+ } else {
+ Param |= 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_FIFO_FLUSH | DWC_XDCI_DGCMD_CMD_ACTIVE_MASK)
+ );
+
+
+ //
+ // Wait until command completes
+ //
+ do {
+ if (!(UsbRegRead(BaseAddr, DWC_XDCI_DGCMD_REG) & DWC_XDCI_DGCMD_CMD_ACTIVE_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 = EFI_DEVICE_ERROR;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpCancelTransfer: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get physical EP num
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+ Status = 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 = EFI_DEVICE_ERROR;
+ UINT32 BaseAddr;
+ XDCI_CORE_HANDLE *LocalCoreHandle;
+ DWC_XDCI_ENDPOINT_CMD_PARAMS EpCmdParams;
+ UINT32 MaxDelayIter = DWC_XDCI_MAX_DELAY_ITERATIONS;
+ UINT8 i;
+
+ LocalCoreHandle = CoreHandle;
+
+ if (CoreHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (LocalCoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to allocate handle for xDCI\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BaseAddr = 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 = 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 (BaseAddr, 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_GUSB2PHYCFG_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 = 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 = ((UsbRegRead (BaseAddr, DWC_XDCI_GHWPARAMS1_REG) &
+ DWC_XDCI_GHWPARAMS1_NUM_INT_MASK) >>
+ DWC_XDCI_GHWPARAMS1_NUM_INT_BIT_POS);
+
+ DEBUG ((DEBUG_INFO, "Max dev int lines: %d\n", LocalCoreHandle->MaxDevIntLines));
+ //
+ // 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 = (DWC_XDCI_EVENT_BUFFER *)
+ ((UINT32)(UINTN)(LocalCoreHandle->EventBuffers) +
+ ((sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER) -
+ (((UINT32)(UINTN)(LocalCoreHandle->EventBuffers)) %
+ (sizeof (DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER))));
+
+ for (i = 0; i < LocalCoreHandle->MaxDevIntLines; i++) {
+ UsbRegWrite (
+ BaseAddr,
+ DWC_XDCI_GEVNTADR_REG (i),
+ (UINT32)(UINTN)(LocalCoreHandle->AlignedEventBuffers + i * sizeof(DWC_XDCI_EVENT_BUFFER) * DWC_XDCI_MAX_EVENTS_PER_BUFFER)
+ );
+
+ //
+ // Clear High 32bit address register, GEVNTADR register is 64-bit register
+ // default is 0xffffffffffffffff
+ //
+ UsbRegWrite (BaseAddr, DWC_XDCI_GEVNTADR_REG (i) + 4, 0x00000000);
+
+ LocalCoreHandle->CurrentEventBuffer = LocalCoreHandle->AlignedEventBuffers;
+ //
+ // 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, Count: %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_RAMCLKSEL_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", UsbRegRead (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", UsbRegRead (BaseAddr, DWC_XDCI_DCFG_REG)));
+ DEBUG ((DEBUG_INFO, "Setup value of xDCI DWC_XDCI_DSTS_REG: 0x%x\n", UsbRegRead (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_GUSB2PHYCFG_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_GUSB3PIPECTL_SUSPEND_PHY_MASK)
+ );
+ //
+ // Issue DEPSTARTCFG command for EP0
+ //
+ status = 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 = 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 = 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 = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams);
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP0\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPCFG command for EP1
+ //
+ status = 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 = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_SET_EP_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue SET_EP_CONFIG command on xDCI for EP1\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPXFERCFG command for EP0
+ //
+ status = 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 = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 0,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP0\n"));
+ return status;
+ }
+
+ //
+ // Issue DEPXFERCFG command for EP1
+ //
+ status = 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 = DwcXdciCoreIssueEpCmd (
+ LocalCoreHandle,
+ 1,
+ EPCMD_SET_EP_XFER_RES_CONFIG,
+ &EpCmdParams
+ );
+
+ if (status) {
+ DEBUG ((DEBUG_INFO, "DwcXdciCoreInit: Failed to issue EPCMD_SET_EP_XFER_RES_CONFIG command on xDCI for EP1\n"));
+ return status;
+ }
+
+ //
+ // Prepare a Buffer for SETUP packet
+ //
+ LocalCoreHandle->Trbs = (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 = LocalCoreHandle->DefaultSetupBuffer +
+ (DWC_XDCI_SETUP_BUFF_SIZE -
+ ((UINT32)(UINTN)(LocalCoreHandle->DefaultSetupBuffer) % DWC_XDCI_SETUP_BUFF_SIZE));
+
+ //
+ // Aligned Buffer for status phase
+ //
+ LocalCoreHandle->AlignedMiscBuffer = LocalCoreHandle->MiscBuffer +
+ (DWC_XDCI_SETUP_BUFF_SIZE -
+ ((UINT32)(UINTN)(LocalCoreHandle->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 = EFI_DEVICE_ERROR;
+ UINT32 EpNum;
+
+ if (CoreHandle == NULL) {
+ DEBUG ((DEBUG_INFO, "DwcXdciEpCancelTransfer: INVALID handle\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get physical EP num
+ //
+ EpNum = DwcXdciGetPhysicalEpNum (EpInfo->EpNum, EpInfo->EpDir);
+ DwcXdciCoreFlushEpFifo(CoreHandle, EpNum);
+
+ return Status;
+}
+#pragma optimize ("", on)
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.h new file mode 100644 index 0000000000..3470cfd15e --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDWC.h @@ -0,0 +1,741 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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_NUM - 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_DEVTEN_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_RESUME_WAKEUP_DET_EN_MASK | \
+ DWC_XDCI_DEVTEN_HIBERNATION_REQ_EN_MASK | DWC_XDCI_DEVTEN_U3L2L1_DET_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 = 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 = 9
+} DWC_XDCI_ENDPOINT_CMD;
+
+typedef enum {
+ ON = 0,
+ SLEEP = 2,
+ SUSPEND,
+ DISCONNECTED,
+ EARLY_SUSPEND,
+ RESET = 14,
+ RESUME = 15
+} DWC_XDCI_HS_LINK_STATE;
+
+typedef enum {
+ TRBCTL_NORMAL = 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) * DWC_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/XdciDevice.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDevice.c new file mode 100644 index 0000000000..2dcd44881b --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDevice.c @@ -0,0 +1,695 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/UsbDeviceLib.h>
+#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 = EFI_INVALID_PARAMETER;
+
+ DEBUG ((DEBUG_INFO, "Call UsbDeviceInit start\n"));
+
+ //
+ // Allocate device handle
+ //
+ DevCorePtr = AllocateZeroPool (sizeof (USB_DEV_CORE));
+ DEBUG ((DEBUG_INFO, "device handle = 0x%x\n", DevCorePtr));
+
+ if (DevCorePtr == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInit. ERROR: Failed to allocate memory\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG ((DEBUG_INFO, "call UsbDeviceGetCoreDriver, ID=%x, \n", ConfigParams->ControllerId));
+
+ //
+ // Get the driver for this USB device core
+ //
+ DevCorePtr->CoreDriver = UsbDeviceGetCoreDriver(ConfigParams->ControllerId);
+ if (DevCorePtr->CoreDriver != NULL) {
+ DEBUG ((DEBUG_INFO, "call DevCoreInit\n"));
+ Status = DevCorePtr->CoreDriver->DevCoreInit(
+ ConfigParams,
+ (VOID*)DevCorePtr,
+ &DevCorePtr->ControllerHandle);
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInit. ERROR: Driver not found\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *DevCoreHandle = (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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (Core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceDeinit: ERROR: INVALID HANDLE\n"));
+ } else {
+ if (Core->CoreDriver != NULL) {
+ Status = Core->CoreDriver->DevCoreDeinit(
+ Core->ControllerHandle,
+ Flags
+ );
+ FreePool(DevCoreHandle);
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceDeinit: Driver not found\n"));
+ Status = 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 = EFI_DEVICE_ERROR;
+ USB_DEV_CORE *core = (USB_DEV_CORE *)DevCoreHandle;
+
+ DEBUG ((DEBUG_INFO, "UsbDeviceRegisterCallback start\n"));
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceRegisterCallback: ERROR: INVALID HANDLE\n"));
+ } else {
+ if (core->CoreDriver != NULL) {
+ DEBUG ((DEBUG_INFO, "Call DevCoreRegisterCallback\n"));
+ Status = 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 = EFI_DEVICE_ERROR;
+ USB_DEV_CORE *core = (USB_DEV_CORE *)DevCoreHandle;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceUnregisterCallback: ERROR: INVALID HANDLE\n"));
+ } else {
+ if (core->CoreDriver != NULL) {
+ Status = 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceIsrRoutine: ERROR: INVALID HANDLE\n"));
+ } else {
+ if (core->CoreDriver != NULL) {
+ Status = core->CoreDriver->DevCoreIsrRoutine (core->ControllerHandle);
+ }
+ }
+
+ 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceIsrRoutine: ERROR: INVALID HANDLE\n"));
+ } else {
+ if (core->CoreDriver != NULL) {
+ Status = core->CoreDriver->DevCoreIsrRoutineTimerBased (core->ControllerHandle);
+ }
+ }
+
+ 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbXdciDeviceConnect: ERROR: INVALID HANDLE\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbXdciDeviceConnect\n"));
+ Status = 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 =(USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceDisconnect: ERROR: INVALID HANDLE\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "UsbDeviceDisconnect\n"));
+ Status = 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceGetSpeed: ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = core->CoreDriver->DevCoreGetSpeed(core->ControllerHandle, Speed);
+ }
+
+ 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ DEBUG ((DEBUG_INFO, "UsbDeviceSetAddress: enter......\n"));
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceSetAddress: ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceSetConfiguration: ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceSetLinkState: ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = core->CoreDriver->DevCoreSetLinkState (core->ControllerHandle, 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceInitEp: ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = core->CoreDriver->DevCoreInitEp (core->ControllerHandle, EpInfo);
+ }
+
+ 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceEpEnable: ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceEpDisable ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceEpStall ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = core->CoreDriver->DevCoreEpStall (core->ControllerHandle, EpInfo);
+ }
+
+ 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceEpClearStall ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = core->CoreDriver->DevCoreEpClearStall (core->ControllerHandle, 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceEpSetNrdy ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceEp0RxSetup ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = core->CoreDriver->DevCoreEp0RxSetupPkt (core->ControllerHandle, 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceEp0RxStatus ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = core->CoreDriver->DevCoreEp0RxStatusPkt (core->ControllerHandle);
+ }
+ 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceEp0TxStatus ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = core->CoreDriver->DevCoreEp0TxStatusPkt (core->ControllerHandle);
+ }
+
+ 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 length
+ 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbXdciDeviceEpTxData ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = 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 length
+ 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbXdciDeviceEpRxData ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = 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 = (USB_DEV_CORE *)DevCoreHandle;
+ EFI_STATUS Status = EFI_DEVICE_ERROR;
+
+ if (core == NULL) {
+ DEBUG ((DEBUG_INFO, "UsbDeviceEpCancelTransfer ERROR: INVALID HANDLE\n"));
+ } else {
+ Status = core->CoreDriver->DevCoreEpCancelTransfer (core->ControllerHandle, EpInfo);
+ }
+
+ return Status;
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDevice.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDevice.h new file mode 100644 index 0000000000..aee6bdef70 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciDevice.h @@ -0,0 +1,184 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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 registers 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/XdciInterface.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciInterface.h new file mode 100644 index 0000000000..90264e84f5 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciInterface.h @@ -0,0 +1,241 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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/XdciTable.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciTable.c new file mode 100644 index 0000000000..31990ae921 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciTable.c @@ -0,0 +1,55 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/UsbDeviceLib.h>
+#include "XdciCommon.h"
+#include "XdciDevice.h"
+#include "XdciInterface.h"
+#include "XdciDWC.h"
+#include "UsbDeviceMode.h"
+
+static const struct UsbDeviceCoreDriver CoreDriverTbl[USB_CORE_ID_MAX] = {
+ 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 >= USB_CORE_ID_MAX)
+ return NULL;
+
+ return &CoreDriverTbl[id];
+}
+
diff --git a/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciUtility.c b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciUtility.c new file mode 100644 index 0000000000..2a756b9d16 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciUtility.c @@ -0,0 +1,148 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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->DescriptorType));
+ 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->DeviceSubClass));
+ DEBUG ((DEBUG_INFO, "DeviceProtocol : 0x%x\n", DevDesc->DeviceProtocol));
+ DEBUG ((DEBUG_INFO, "MaxPacketSize0 : 0x%x\n", DevDesc->MaxPacketSize0));
+ 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->StrManufacturer));
+ DEBUG ((DEBUG_INFO, "StrProduct : 0x%x\n", DevDesc->StrProduct));
+ DEBUG ((DEBUG_INFO, "StrSerialNumber : 0x%x\n", DevDesc->StrSerialNumber));
+ DEBUG ((DEBUG_INFO, "NumConfigurations : 0x%x\n", DevDesc->NumConfigurations));
+ 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->DescriptorType));
+ DEBUG ((DEBUG_INFO, "TotalLength : 0x%x\n", ConfigDesc->TotalLength));
+ DEBUG ((DEBUG_INFO, "NumInterfaces : 0x%x\n", ConfigDesc->NumInterfaces));
+ DEBUG ((DEBUG_INFO, "ConfigurationValue : 0x%x\n", ConfigDesc->ConfigurationValue));
+ DEBUG ((DEBUG_INFO, "Configuration : 0x%x\n", ConfigDesc->Configuration));
+ DEBUG ((DEBUG_INFO, "Attributes : 0x%x\n", ConfigDesc->Attributes));
+ 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->InterfaceNumber));
+ DEBUG ((DEBUG_INFO, "AlternateSetting : 0x%x\n", IfDesc->AlternateSetting));
+ 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->InterfaceSubClass));
+ DEBUG ((DEBUG_INFO, "InterfaceProtocol : 0x%x\n", IfDesc->InterfaceProtocol));
+ 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->BytesPerInterval));
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+VOID
+PrintStringDescriptor (
+ IN USB_STRING_DESCRIPTOR *StrDesc
+ )
+{
+ UINT16 StrLen = 0;
+
+ if (StrDesc->Length > 2) {
+ StrLen = ((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/XdciUtility.h b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciUtility.h new file mode 100644 index 0000000000..c243a5b3fb --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Features/UsbDeviceDxe/XdciUtility.h @@ -0,0 +1,62 @@ +/** @file
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _XDCI_UTILITY_H_
+#define _XDCI_UTILITY_H_
+
+#include <Library/UsbDeviceLib.h>
+
+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 0000000000..7b1d4a9d6d --- /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.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_USB_FUNC_IO_H__
+#define __EFI_USB_FUNC_IO_H__
+
+#include <IndustryStandard/Usb.h>
+
+#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 = 0,
+ EfiUsbStandardDownstreamPort,
+ EfiUsbChargingDownstreamPort,
+ EfiUsbDedicatedChargingPort,
+ EfiUsbInvalidDedicatedChargingPort
+} EFI_USBFN_PORT_TYPE;
+
+/**
+ USB_DEVICE_DESCRIPTOR, USB_CONFIG_DESCRIPTOR, USB_INTERFACE_DESCRIPTOR, and
+ 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 = 0x00,
+ UsbEndpointIsochronous = 0x01,
+ UsbEndpointBulk = 0x02,
+ UsbEndpointInterrupt = 0x03
+} EFI_USB_ENDPOINT_TYPE;
+
+
+typedef enum _EFI_USBFN_DEVICE_INFO_ID {
+ EfiUsbDeviceInfoUnknown = 0,
+ EfiUsbDeviceInfoSerialNumber,
+ EfiUsbDeviceInfoManufacturerName,
+ EfiUsbDeviceInfoProductName
+} EFI_USBFN_DEVICE_INFO_ID;
+
+
+typedef enum _EFI_USBFN_ENDPOINT_DIRECTION {
+ EfiUsbEndpointDirectionHostOut = 0,
+ EfiUsbEndpointDirectionHostIn,
+ EfiUsbEndpointDirectionDeviceTx = EfiUsbEndpointDirectionHostIn,
+ EfiUsbEndpointDirectionDeviceRx = EfiUsbEndpointDirectionHostOut
+} EFI_USBFN_ENDPOINT_DIRECTION;
+
+
+typedef enum _EFI_USBFN_MESSAGE {
+ //
+ // Nothing
+ //
+ EfiUsbMsgNone = 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 any
+ // 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 = 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 = 0,
+ UsbBusSpeedLow,
+ UsbBusSpeedFull,
+ UsbBusSpeedHigh,
+ UsbBusSpeedSuper,
+ UsbBusSpeedMaximum = 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 = 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 bytes 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 AllocateTransferBuffer 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 descriptors.
+**/
+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 supplied 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 endpoint 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 specified
+ 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-control 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-control 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/UsbDeviceModeProtocol.h b/Platform/BroxtonPlatformPkg/Common/Include/Protocol/UsbDeviceModeProtocol.h new file mode 100644 index 0000000000..bd8d85fdd7 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Include/Protocol/UsbDeviceModeProtocol.h @@ -0,0 +1,104 @@ +/** @file
+ Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef _USB_DEVICE_MODE_PROTOCOL_H_
+#define _USB_DEVICE_MODE_PROTOCOL_H_
+
+#include <Library/UsbDeviceLib.h>
+
+///
+/// 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 0000000000..570bc2105b --- /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.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/PmicLib.h>
+#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 device.
+ @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 specified
+ by Value and return the operation status.
+
+ @param[in] BaseAddress - IPC operation address for target PMIC device.
+ @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 = {
+ 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,
+
+ //
+ //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 0000000000..b0abe480cf --- /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.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include "PmicPrivate.h"
+
+
+struct PmicObject *gPmicObj = NULL;
+
+extern struct PmicObject DmObj;
+
+
+struct PmicObject *gPmicSupportList[] = {
+ &DmObj, //dummy
+};
+
+
+PMIC_TYPE gPmicType = 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 device.
+ @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 specified
+ by Value and return the operation status.
+
+ @param[in] BaseAddress - IPC operation address for target PMIC device.
+ @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, interrupts,
+ and output actions) that allow the Software and Firmware to change the BCU response
+ behavior once these events occur. These BCU control knobs allow for a change in the
+ BCU behavior in responding to these triggers and can be completely customized 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 successfully.
+ @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 successfully,
+ 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 = &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 of 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 is 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 0000000000..35ceb79d53 --- /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.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PmicLibNull
+ FILE_GUID = 90c0faf8-cb8b-4726-a69c-c38a5b110c30
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PmicLib
+ CONSTRUCTOR = PmicLibConstructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = 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 0000000000..c173b38674 --- /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.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+
+#ifndef _PMIC_REG_PV_H_
+#define _PMIC_REG_PV_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Base.h>
+#include <Library/PmicLib.h>
+
+///
+/// PMIC device object
+///
+struct PmicObject {
+ UINT8 I2cbus;
+ UINT8 I2cSlaveAddr0; ///< page0
+ UINT8 I2cSlaveAddr1; ///< page1
+ PMIC_TYPE PmicType;
+ UINT8 (EFIAPI* PmicRead8) (IN UINT8 BaseAddress, IN UINT8 Register);
+ EFI_STATUS (EFIAPI* PmicWrite8) (IN UINT8 BaseAddress, IN UINT8 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 *ShutdownCause);
+ 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 Value);
+ 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 == gPmicObj) || (NULL == gPmicObj->method)) \
+ {\
+ DEBUG ((DEBUG_ERROR, "null function pointer\n")); \
+ return value; \
+ }\
+ }
+
+#endif
+
diff --git a/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/SouthClusterConfig.vfi b/Platform/BroxtonPlatformPkg/Common/PlatformSettings/PlatformSetupDxe/SouthClusterConfig.vfi index 84ae466730..411006b384 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.<BR>
+// Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
//
// 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 = USB_OPTIONS_FORM_ID, oneof varid = Setup.ScUsbOtg,
prompt = STRING_TOKEN(STR_USB_XDCI_PROMPT),
help = STRING_TOKEN(STR_USB_XDCI_HELP),
- option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;
- option text = STRING_TOKEN(STR_PCI_MODE_STRING), value = 1, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_DISABLE), value = 0, flags = RESET_REQUIRED;
+ option text = STRING_TOKEN(STR_PCI_MODE_STRING), value = 1, flags = DEFAULT | MANUFACTURING | RESET_REQUIRED;
// option text = STRING_TOKEN(STR_ACPI_MODE_STRING), value = 2, flags = RESET_REQUIRED;
endoneof;
|