From nobody Sun Apr 28 23:08:54 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1511173694456670.9350494255486; Mon, 20 Nov 2017 02:28:14 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 910AC2034712D; Mon, 20 Nov 2017 02:23:58 -0800 (PST) Received: from mail-pf0-x243.google.com (mail-pf0-x243.google.com [IPv6:2607:f8b0:400e:c00::243]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 913A020347121 for ; Mon, 20 Nov 2017 02:23:56 -0800 (PST) Received: by mail-pf0-x243.google.com with SMTP id 17so6971620pfn.12 for ; Mon, 20 Nov 2017 02:28:10 -0800 (PST) Received: from localhost.localdomain ([220.225.120.129]) by smtp.gmail.com with ESMTPSA id m87sm5136203pfi.88.2017.11.20.02.28.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 20 Nov 2017 02:28:05 -0800 (PST) X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:400e:c00::243; helo=mail-pf0-x243.google.com; envelope-from=kalyankumar.nagabhirava@linaro.org; receiver=edk2-devel@lists.01.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=JN8q5IkE/LFeovOqaOwwiu8fGjrKZDglpCnGXNu6X/4=; b=YK1vP/5C86FPRafhjSyr6eetWLtJ1Swt+BHqobIzkTaFx1E7S+b1ccBI82HCe7I7ff S4tpM1vjIOSsHe3ucClQG7diKxc6x/pn7r/0jXboFKIV4Tf+NWR0lJNLulRLJ1NLM44h shjmhFCamtosmR8UclKNnVA/y4IO/A9eGZDWw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=JN8q5IkE/LFeovOqaOwwiu8fGjrKZDglpCnGXNu6X/4=; b=l6plSlnNrAM+3vgF/ZhirRZyPvzelUO1HPGLLsIk5axP/0SsdFLMVl1XRMPZ26k6gR r23vqk/TuAL8l6YZWfq6xKrBUKrB8wFG50rsrwusiU+cErplbK/qXX/e0QevvqGs+Z6A dr28KxE/gxCIAfu1nXJdKvPn5Z9JgV7kObY/h6NrfCczQUa3vxGslyhRbyM2NFKw5Ts9 KohlxCtqIlK+yjd3f729lE0Fu9e7yWslNLms07kNCn6eNGUggMFWxwgmk/G4wkQHIuye 0ip/k4yOpqRY9Hhx6W4cYL/dBudVfYkXtXFzwipCrzlOldo1eH8ovhv87vnmGk1PVoHJ ggKw== X-Gm-Message-State: AJaThX5rJUl8KskBIgcCOcvbsepoghQTV2k00+6x57beDi4NxUwdWVB4 s3ZXWSBhaRhl9cq7jFUFXRwWWMDbetM= X-Google-Smtp-Source: AGs4zMYgh4H38AeCSOjVyIuy2wSHpgcwbGM9Mv6OMvzTh2DrMutYbdsq5Q2TgLyg4qaJhXnbM7z1WQ== X-Received: by 10.84.215.207 with SMTP id g15mr13194588plj.369.1511173686358; Mon, 20 Nov 2017 02:28:06 -0800 (PST) From: kalyan-nagabhirava To: edk2-devel@lists.01.org, ard.biesheuvel@linaro.org, leif.lindholm@linaro.org Date: Mon, 20 Nov 2017 15:55:44 +0530 Message-Id: <20171120102544.21532-1-kalyankumar.nagabhirava@linaro.org> X-Mailer: git-send-email 2.15.0 Subject: [edk2] [PATCH] [edk2-platforms]: Adding usb Host driver support from OpenPlatformPkg hikey-wip branch X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.griffin@linaro.org, mark.gregotski@linaro.org MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: kalyan-nagabhirava --- Platform/Hisilicon/HiKey/HiKey.dec | 4 + Platform/Hisilicon/HiKey/HiKey.dsc | 11 + Platform/Hisilicon/HiKey/HiKey.fdf | 3 + .../Include/Library/UncachedMemoryAllocationLib.h | 665 ++++++ .../Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.c | 342 +++ .../HiKey/Library/ArmDmaLib/ArmDmaLib.inf | 50 + .../UncachedMemoryAllocationLib.c | 692 ++++++ .../UncachedMemoryAllocationLib.inf | 45 + Silicon/Synopsys/Usb/DwNonPci/DwNonPciUsbDxe.inf | 47 + Silicon/Synopsys/Usb/DwNonPci/InitController.c | 37 + Silicon/Synopsys/Usb/DwUsbDxe/ComponentName.c | 244 ++ Silicon/Synopsys/Usb/DwUsbDxe/ComponentName.h | 148 ++ Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.c | 2324 ++++++++++++++++= ++++ Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.dec | 42 + Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.h | 534 +++++ Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.inf | 60 + Silicon/Synopsys/Usb/DwUsbHostDxe/ComponentName.c | 243 ++ Silicon/Synopsys/Usb/DwUsbHostDxe/ComponentName.h | 148 ++ Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.c | 2043 +++++++++++++++++ Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.h | 121 + Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.inf | 61 + Silicon/Synopsys/Usb/DwUsbHostDxe/DwcHw.h | 792 +++++++ 22 files changed, 8656 insertions(+) create mode 100644 Platform/Hisilicon/HiKey/Include/Library/UncachedMemory= AllocationLib.h create mode 100644 Platform/Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.c create mode 100644 Platform/Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.inf create mode 100644 Platform/Hisilicon/HiKey/Library/UncachedMemoryAllocati= onLib/UncachedMemoryAllocationLib.c create mode 100644 Platform/Hisilicon/HiKey/Library/UncachedMemoryAllocati= onLib/UncachedMemoryAllocationLib.inf create mode 100644 Silicon/Synopsys/Usb/DwNonPci/DwNonPciUsbDxe.inf create mode 100644 Silicon/Synopsys/Usb/DwNonPci/InitController.c create mode 100644 Silicon/Synopsys/Usb/DwUsbDxe/ComponentName.c create mode 100644 Silicon/Synopsys/Usb/DwUsbDxe/ComponentName.h create mode 100644 Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.c create mode 100644 Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.dec create mode 100644 Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.h create mode 100644 Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.inf create mode 100644 Silicon/Synopsys/Usb/DwUsbHostDxe/ComponentName.c create mode 100644 Silicon/Synopsys/Usb/DwUsbHostDxe/ComponentName.h create mode 100644 Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.c create mode 100644 Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.h create mode 100644 Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.inf create mode 100644 Silicon/Synopsys/Usb/DwUsbHostDxe/DwcHw.h diff --git a/Platform/Hisilicon/HiKey/HiKey.dec b/Platform/Hisilicon/HiKey/= HiKey.dec index 537138eb4..a1f610bf0 100644 --- a/Platform/Hisilicon/HiKey/HiKey.dec +++ b/Platform/Hisilicon/HiKey/HiKey.dec @@ -34,3 +34,7 @@ [PcdsFixedAtBuild.common] gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L""|VOID*|0x00000001 gHiKeyTokenSpaceGuid.PcdArmFastbootFlashLimit|L""|VOID*|0x00000002 + =20 + # This PCD will free the unallocated buffers if their size reach this th= reshold. + # We set the default value to 512MB. + gArmTokenSpaceGuid.PcdArmFreeUncachedMemorySizeThreshold|0x20000000|UINT= 64|0x00000003 diff --git a/Platform/Hisilicon/HiKey/HiKey.dsc b/Platform/Hisilicon/HiKey/= HiKey.dsc index 2e3b1c879..497361454 100644 --- a/Platform/Hisilicon/HiKey/HiKey.dsc +++ b/Platform/Hisilicon/HiKey/HiKey.dsc @@ -109,6 +109,10 @@ =20 # USB Requirements UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + DmaLib|Platform/Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.inf + + UncachedMemoryAllocationLib|Platform/Hisilicon/HiKey/Library/UncachedMem= oryAllocationLib/UncachedMemoryAllocationLib.inf + NonDiscoverableDeviceRegistrationLib|MdeModulePkg/Library/NonDiscoverabl= eDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.inf =20 # Network Libraries UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf @@ -330,7 +334,11 @@ gEmbeddedTokenSpaceGuid.PcdDwEmmcDxeBaseAddress|0xF723D000 gEmbeddedTokenSpaceGuid.PcdDwEmmcDxeClockFrequencyInHz|100000000 =20 + # DW USB controller # + gDwUsbDxeTokenSpaceGuid.PcdDwUsbBaseAddress|0xF72c0000 + gDwUsbDxeTokenSpaceGuid.PcdDwUsbSysCtrlBaseAddress|0xF7030000 + # # Fastboot # @@ -399,6 +407,9 @@ # USB Host Support # MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.inf + Silicon/Synopsys/Usb/DwNonPci/DwNonPciUsbDxe.inf + MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDevic= eDxe.inf =20 # # USB Mass Storage Support diff --git a/Platform/Hisilicon/HiKey/HiKey.fdf b/Platform/Hisilicon/HiKey/= HiKey.fdf index d277bd6ce..78ba85399 100644 --- a/Platform/Hisilicon/HiKey/HiKey.fdf +++ b/Platform/Hisilicon/HiKey/HiKey.fdf @@ -129,6 +129,9 @@ READ_LOCK_STATUS =3D TRUE # USB Host Support # INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + INF Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.inf + INF Silicon/Synopsys/Usb/DwNonPci/DwNonPciUsbDxe.inf + INF MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciD= eviceDxe.inf =20 # # USB Mass Storage Support diff --git a/Platform/Hisilicon/HiKey/Include/Library/UncachedMemoryAllocat= ionLib.h b/Platform/Hisilicon/HiKey/Include/Library/UncachedMemoryAllocatio= nLib.h new file mode 100644 index 000000000..a49d8d3ac --- /dev/null +++ b/Platform/Hisilicon/HiKey/Include/Library/UncachedMemoryAllocationLib.h @@ -0,0 +1,665 @@ +/** @file + + Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#ifndef __UNCACHED_MEMORY_ALLOCATION_LIB_H__ +#define __UNCACHED_MEMORY_ALLOCATION_LIB_H__ + +/** + Converts a cached or uncached address to a physical address suitable for= use in SoC registers. + + @param VirtualAddress The pointer to convert. + + @return The physical address of the supplied virtual pointer. + +**/ +EFI_PHYSICAL_ADDRESS +ConvertToPhysicalAddress ( + IN VOID *VirtualAddress + ); + +/** + Converts a cached or uncached address to a cached address. + + @param Address The pointer to convert. + + @return The address of the cached memory location corresponding to the i= nput address. + +**/ +VOID * +ConvertToCachedAddress ( + IN VOID *Address + ); + +/** + Converts a cached or uncached address to an uncached address. + + @param Address The pointer to convert. + + @return The address of the uncached memory location corresponding to the= input address. + +**/ +VOID * +ConvertToUncachedAddress ( + IN VOID *Address + ); + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of type EfiBootServicesData and return= s a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If= Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the req= uest, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocatePages ( + IN UINTN Pages + ); + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData and ret= urns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If= Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the req= uest, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimePages ( + IN UINTN Pages + ); + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType. + + Allocates the number of 4KB pages of type EfiReservedMemoryType and retu= rns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If= Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the req= uest, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedPages ( + IN UINTN Pages + ); + +/** + Frees one or more 4KB pages that were previously allocated with one of t= he page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specifi= ed by Buffer. Buffer + must have been allocated on a previous call to the page allocation servi= ces of the Memory + Allocation Library. + If Buffer was not allocated with a page allocation function in the Memor= y Allocation Library, + then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +UncachedFreePages ( + IN VOID *Buffer, + IN UINTN Pages + ); + +/** + Allocates one or more 4KB pages of type EfiBootServicesData at a specifi= ed alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiBootServ= icesData with an + alignment specified by Alignment. The allocated buffer is returned. If= Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment rema= ining to satisfy the + request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a spec= ified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeS= ervicesData with an + alignment specified by Alignment. The allocated buffer is returned. If= Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment rema= ining to satisfy the + request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a speci= fied alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiReserved= MemoryType with an + alignment specified by Alignment. The allocated buffer is returned. If= Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment rema= ining to satisfy the + request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +/** + Frees one or more 4KB pages that were previously allocated with one of t= he aligned page + allocation functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specifi= ed by Buffer. Buffer + must have been allocated on a previous call to the aligned page allocati= on services of the Memory + Allocation Library. + If Buffer was not allocated with an aligned page allocation function in = the Memory Allocation + Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +UncachedFreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ); + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootSe= rvicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid b= uffer of 0 size is + returned. If there is not enough memory remaining to satisfy the reques= t, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocatePool ( + IN UINTN AllocationSize + ); + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntim= eServicesData and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid= buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the reques= t, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimePool ( + IN UINTN AllocationSize + ); + +/** + Allocates a buffer of type EfieservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type Efieserve= dMemoryType and returns + a pointer to the allocated buffer. If AllocationSize is 0, then a valid= buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the reques= t, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedPool ( + IN UINTN AllocationSize + ); + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootSe= rvicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If Al= locationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remai= ning to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateZeroPool ( + IN UINTN AllocationSize + ); + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntim= eServicesData, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If Al= locationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remai= ning to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ); + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReserv= edMemoryType, clears the + buffer with zeros, and returns a pointer to the allocated buffer. If Al= locationSize is 0, then a + valid buffer of 0 size is returned. If there is not enough memory remai= ning to satisfy the + request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedZeroPool ( + IN UINTN AllocationSize + ); + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootSe= rvicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and retu= rns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size= is returned. If there + is not enough memory remaining to satisfy the request, then NULL is retu= rned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSER= T(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntim= eServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and retu= rns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size= is returned. If there + is not enough memory remaining to satisfy the request, then NULL is retu= rned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSER= T(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReserv= edMemoryType, copies + AllocationSize bytes from Buffer to the newly allocated buffer, and retu= rns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size= is returned. If there + is not enough memory remaining to satisfy the request, then NULL is retu= rned. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSER= T(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + +/** + Frees a buffer that was previously allocated with one of the pool alloca= tion functions in the + Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated o= n a previous call to the + pool allocation services of the Memory Allocation Library. + If Buffer was not allocated with a pool allocation function in the Memor= y Allocation Library, + then ASSERT(). + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +UncachedFreePool ( + IN VOID *Buffer + ); + +/** + Allocates a buffer of type EfiBootServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiBootSe= rvicesData with an + alignment specified by Alignment. The allocated buffer is returned. If= AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memor= y at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates a buffer of type EfiRuntimeServicesData at a specified alignme= nt. + + Allocates the number bytes specified by AllocationSize of type EfiRuntim= eServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If= AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memor= y at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedRuntimePool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates a buffer of type EfieservedMemoryType at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type Efieserve= dMemoryType with an + alignment specified by Alignment. The allocated buffer is returned. If= AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memor= y at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedReservedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates and zeros a buffer of type EfiBootServicesData at a specified = alignment. + + Allocates the number bytes specified by AllocationSize of type EfiBootSe= rvicesData with an + alignment specified by Alignment, clears the buffer with zeros, and retu= rns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size= is returned. If there + is not enough memory at the specified alignment remaining to satisfy the= request, then NULL is + returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData at a specifi= ed alignment. + + Allocates the number bytes specified by AllocationSize of type EfiRuntim= eServicesData with an + alignment specified by Alignment, clears the buffer with zeros, and retu= rns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size= is returned. If there + is not enough memory at the specified alignment remaining to satisfy the= request, then NULL is + returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedRuntimeZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates and zeros a buffer of type EfieservedMemoryType at a specified= alignment. + + Allocates the number bytes specified by AllocationSize of type Efieserve= dMemoryType with an + alignment specified by Alignment, clears the buffer with zeros, and retu= rns a pointer to the + allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size= is returned. If there + is not enough memory at the specified alignment remaining to satisfy the= request, then NULL is + returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedReservedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData at a = specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiBootSe= rvicesData type with an + alignment specified by Alignment. The allocated buffer is returned. If= AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memor= y at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ); + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData at= a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiRuntim= eServicesData type with an + alignment specified by Alignment. The allocated buffer is returned. If= AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memor= y at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ); + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType at = a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiReserv= edMemoryType type with an + alignment specified by Alignment. The allocated buffer is returned. If= AllocationSize is 0, + then a valid buffer of 0 size is returned. If there is not enough memor= y at the specified + alignment remaining to satisfy the request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSER= T(). + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation.= Must be a power of two. + If Alignment is zero, then byte alignment = is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateAlignedReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ); + +/** + Frees a buffer that was previously allocated with one of the aligned poo= l allocation functions + in the Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated o= n a previous call to the + aligned pool allocation services of the Memory Allocation Library. + If Buffer was not allocated with an aligned pool allocation function in = the Memory Allocation + Library, then ASSERT(). + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +UncachedFreeAlignedPool ( + IN VOID *Buffer + ); + +VOID +EFIAPI +UncachedSafeFreePool ( + IN VOID *Buffer + ); + +#endif // __UNCACHED_MEMORY_ALLOCATION_LIB_H__ diff --git a/Platform/Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.c b/Platf= orm/Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.c new file mode 100644 index 000000000..f4ee9e4c5 --- /dev/null +++ b/Platform/Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.c @@ -0,0 +1,342 @@ +/** @file + Generic ARM implementation of DmaLib.h + + Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +typedef struct { + EFI_PHYSICAL_ADDRESS HostAddress; + VOID *BufferAddress; + UINTN NumberOfBytes; + DMA_MAP_OPERATION Operation; + BOOLEAN DoubleBuffer; +} MAP_INFO_INSTANCE; + + + +STATIC EFI_CPU_ARCH_PROTOCOL *mCpu; + +STATIC +PHYSICAL_ADDRESS +HostToDeviceAddress ( + IN PHYSICAL_ADDRESS HostAddress + ) +{ + return HostAddress + PcdGet64 (PcdArmDmaDeviceOffset); +} + +/** + Provides the DMA controller-specific addresses needed to access system m= emory. + + Operation is relative to the DMA bus master. + + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the DM= A controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to = a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requ= ested address. + +**/ +EFI_STATUS +EFIAPI +DmaMap ( + IN DMA_MAP_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + MAP_INFO_INSTANCE *Map; + VOID *Buffer; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; + + if (HostAddress =3D=3D NULL || NumberOfBytes =3D=3D NULL || DeviceAddres= s =3D=3D NULL || Mapping =3D=3D NULL ) { + return EFI_INVALID_PARAMETER; + } + + if (Operation >=3D MapOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + // + // The debug implementation of UncachedMemoryAllocationLib in ArmPkg ret= urns + // a virtual uncached alias, and unmaps the cached ID mapping of the buf= fer, + // in order to catch inadvertent references to the cached mapping. + // Since HostToDeviceAddress () expects ID mapped input addresses, conve= rt + // the host address to an ID mapped address first. + // + *DeviceAddress =3D HostToDeviceAddress (ConvertToPhysicalAddress (HostAd= dress)); + + // Remember range so we can flush on the other side + Map =3D AllocatePool (sizeof (MAP_INFO_INSTANCE)); + if (Map =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if ((((UINTN)HostAddress & (mCpu->DmaBufferAlignment - 1)) !=3D 0) || + ((*NumberOfBytes & (mCpu->DmaBufferAlignment - 1)) !=3D 0)) { + + // Get the cacheability of the region + Status =3D gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDesc= riptor); + if (EFI_ERROR(Status)) { + goto FreeMapInfo; + } + + // If the mapped buffer is not an uncached buffer + if ((GcdDescriptor.Attributes & (EFI_MEMORY_WB | EFI_MEMORY_WT)) !=3D = 0) { + // + // Operations of type MapOperationBusMasterCommonBuffer are only all= owed + // on uncached buffers. + // + if (Operation =3D=3D MapOperationBusMasterCommonBuffer) { + DEBUG ((EFI_D_ERROR, + "%a: Operation type 'MapOperationBusMasterCommonBuffer' is only = supported\n" + "on memory regions that were allocated using DmaAllocateBuffer (= )\n", + __FUNCTION__)); + Status =3D EFI_UNSUPPORTED; + goto FreeMapInfo; + } + + // + // If the buffer does not fill entire cache lines we must double buf= fer into + // uncached memory. Device (PCI) address becomes uncached page. + // + Map->DoubleBuffer =3D TRUE; + Status =3D DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES= (*NumberOfBytes), &Buffer); + if (EFI_ERROR (Status)) { + goto FreeMapInfo; + } + + if (Operation =3D=3D MapOperationBusMasterRead) { + CopyMem (Buffer, HostAddress, *NumberOfBytes); + } + + *DeviceAddress =3D HostToDeviceAddress (ConvertToPhysicalAddress (Bu= ffer)); + Map->BufferAddress =3D Buffer; + } else { + Map->DoubleBuffer =3D FALSE; + } + } else { + Map->DoubleBuffer =3D FALSE; + + DEBUG_CODE_BEGIN (); + + // + // The operation type check above only executes if the buffer happens = to be + // misaligned with respect to CWG, but even if it is aligned, we shoul= d not + // allow arbitrary buffers to be used for creating consistent mappings. + // So duplicate the check here when running in DEBUG mode, just to ass= ert + // that we are not trying to create a consistent mapping for cached me= mory. + // + Status =3D gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDesc= riptor); + ASSERT_EFI_ERROR(Status); + + ASSERT (Operation !=3D MapOperationBusMasterCommonBuffer || + (GcdDescriptor.Attributes & (EFI_MEMORY_WB | EFI_MEMORY_WT)) = =3D=3D 0); + + DEBUG_CODE_END (); + + // Flush the Data Cache (should not have any effect if the memory regi= on is uncached) + mCpu->FlushDataCache (mCpu, (UINTN)HostAddress, *NumberOfBytes, + EfiCpuFlushTypeWriteBackInvalidate); + } + + Map->HostAddress =3D (UINTN)HostAddress; + Map->NumberOfBytes =3D *NumberOfBytes; + Map->Operation =3D Operation; + + *Mapping =3D Map; + + return EFI_SUCCESS; + +FreeMapInfo: + FreePool (Map); + + return Status; +} + + +/** + Completes the DmaMapBusMasterRead(), DmaMapBusMasterWrite(), or DmaMapBu= sMasterCommonBuffer() + operation and releases any corresponding resources. + + @param Mapping The mapping value returned from DmaMap*(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target s= ystem memory. + @retval EFI_INVALID_PARAMETER An inconsistency was detected between the = mapping type + and the DoubleBuffer field + +**/ +EFI_STATUS +EFIAPI +DmaUnmap ( + IN VOID *Mapping + ) +{ + MAP_INFO_INSTANCE *Map; + EFI_STATUS Status; + + if (Mapping =3D=3D NULL) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Map =3D (MAP_INFO_INSTANCE *)Mapping; + + Status =3D EFI_SUCCESS; + if (Map->DoubleBuffer) { + ASSERT (Map->Operation !=3D MapOperationBusMasterCommonBuffer); + + if (Map->Operation =3D=3D MapOperationBusMasterCommonBuffer) { + Status =3D EFI_INVALID_PARAMETER; + } else if (Map->Operation =3D=3D MapOperationBusMasterWrite) { + CopyMem ((VOID *)(UINTN)Map->HostAddress, Map->BufferAddress, + Map->NumberOfBytes); + } + + DmaFreeBuffer (EFI_SIZE_TO_PAGES (Map->NumberOfBytes), Map->BufferAddr= ess); + + } else { + if (Map->Operation =3D=3D MapOperationBusMasterWrite) { + // + // Make sure we read buffer from uncached memory and not the cache + // + mCpu->FlushDataCache (mCpu, Map->HostAddress, Map->NumberOfBytes, + EfiCpuFlushTypeInvalidate); + } + } + + FreePool (Map); + + return Status; +} + +/** + Allocates pages that are suitable for an DmaMap() of type MapOperationBu= sMasterCommonBuffer. + mapping. + + @param MemoryType The type of memory to allocate, EfiBootSer= vicesData or + EfiRuntimeServicesData. + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + + @retval EFI_SUCCESS The requeste= d memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal = attribute bits are + MEMORY_WRITE_COMBINE and MEMORY_CACHED. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +EFI_STATUS +EFIAPI +DmaAllocateBuffer ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress + ) +{ + VOID *Allocation; + + if (HostAddress =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // The only valid memory types are EfiBootServicesData and EfiRuntimeSer= vicesData + // + // We used uncached memory to keep coherency + // + if (MemoryType =3D=3D EfiBootServicesData) { + Allocation =3D UncachedAllocatePages (Pages); + } else if (MemoryType =3D=3D EfiRuntimeServicesData) { + Allocation =3D UncachedAllocateRuntimePages (Pages); + } else { + return EFI_INVALID_PARAMETER; + } + + if (Allocation =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *HostAddress =3D Allocation; + + return EFI_SUCCESS; +} + + +/** + Frees memory that was allocated with DmaAllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated range. + + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress = and Pages + was not allocated with DmaAllocateBuffer(). + +**/ +EFI_STATUS +EFIAPI +DmaFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + if (HostAddress =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + UncachedFreePages (HostAddress, Pages); + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +ArmDmaLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // Get the Cpu protocol for later use + Status =3D gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **= )&mCpu); + ASSERT_EFI_ERROR(Status); + + return Status; +} + diff --git a/Platform/Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.inf b/Pla= tform/Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.inf new file mode 100644 index 000000000..9b7dad114 --- /dev/null +++ b/Platform/Hisilicon/HiKey/Library/ArmDmaLib/ArmDmaLib.inf @@ -0,0 +1,50 @@ +#/** @file +# +# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may = 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 IM= PLIED. +# +#**/ + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D ArmDmaLib + FILE_GUID =3D F1BD6B36-B705-43aa-8A28-33F58ED85EFB + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D DmaLib + CONSTRUCTOR =3D ArmDmaLibConstructor + +[Sources.common] + ArmDmaLib.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + + +[LibraryClasses] + DebugLib + DxeServicesTableLib + UefiBootServicesTableLib + MemoryAllocationLib + UncachedMemoryAllocationLib + IoLib + BaseMemoryLib + +[Protocols] + gEfiCpuArchProtocolGuid + +[Guids] + +[Pcd] + gArmTokenSpaceGuid.PcdArmDmaDeviceOffset + +[Depex] + gEfiCpuArchProtocolGuid diff --git a/Platform/Hisilicon/HiKey/Library/UncachedMemoryAllocationLib/U= ncachedMemoryAllocationLib.c b/Platform/Hisilicon/HiKey/Library/UncachedMem= oryAllocationLib/UncachedMemoryAllocationLib.c new file mode 100644 index 000000000..f6c692f9a --- /dev/null +++ b/Platform/Hisilicon/HiKey/Library/UncachedMemoryAllocationLib/Uncached= MemoryAllocationLib.c @@ -0,0 +1,692 @@ +/** @file + UncachedMemoryAllocation lib that uses DXE Service to change cachability= for + a buffer. + + Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+ Copyright (c) 2014, AMR Ltd. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +VOID * +UncachedInternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ); + +VOID * +UncachedInternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ); + + + +// +// Assume all of memory has the same cache attributes, unless we do our ma= gic +// +UINT64 gAttributes; + +typedef struct { + EFI_PHYSICAL_ADDRESS Base; + VOID *Allocation; + UINTN Pages; + EFI_MEMORY_TYPE MemoryType; + BOOLEAN Allocated; + LIST_ENTRY Link; +} FREE_PAGE_NODE; + +STATIC LIST_ENTRY mPageList =3D INITIALIZE_LIST_HEAD_VARIABLE (mPageList); +// Track the size of the non-allocated buffer in the linked-list +STATIC UINTN mFreedBufferSize =3D 0; + +/** + * This function firstly checks if the requested allocation can fit into o= ne + * of the previously allocated buffer. + * If the requested allocation does not fit in the existing pool then + * the function makes a new allocation. + * + * @param MemoryType Type of memory requested for the new allocation + * @param Pages Number of requested page + * @param Alignment Required alignment + * @param Allocation Address of the newly allocated buffer + * + * @return EFI_SUCCESS If the function manage to allocate a buffer + * @return !EFI_SUCCESS If the function did not manage to allocate a buffer + */ +STATIC +EFI_STATUS +AllocatePagesFromList ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment, + OUT VOID **Allocation + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + FREE_PAGE_NODE *Node; + FREE_PAGE_NODE *NewNode; + UINTN AlignmentMask; + EFI_PHYSICAL_ADDRESS Memory; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + + // Alignment must be a power of two or zero. + ASSERT ((Alignment & (Alignment - 1)) =3D=3D 0); + + // + // Look in our list for the smallest page that could satisfy the new all= ocation + // + Node =3D NULL; + NewNode =3D NULL; + for (Link =3D mPageList.ForwardLink; Link !=3D &mPageList; Link =3D Link= ->ForwardLink) { + Node =3D BASE_CR (Link, FREE_PAGE_NODE, Link); + if ((Node->Allocated =3D=3D FALSE) && (Node->MemoryType =3D=3D MemoryT= ype)) { + // We have a node that fits our requirements + if (((UINTN)Node->Base & (Alignment - 1)) =3D=3D 0) { + // We found a page that matches the page size + if (Node->Pages =3D=3D Pages) { + Node->Allocated =3D TRUE; + Node->Allocation =3D (VOID*)(UINTN)Node->Base; + *Allocation =3D Node->Allocation; + + // Update the size of the freed buffer + mFreedBufferSize -=3D Pages * EFI_PAGE_SIZE; + return EFI_SUCCESS; + } else if (Node->Pages > Pages) { + if (NewNode =3D=3D NULL) { + // It is the first node that could contain our new allocation + NewNode =3D Node; + } else if (NewNode->Pages > Node->Pages) { + // This node offers a smaller number of page. + NewNode =3D Node; + } + } + } + } + } + // Check if we have found a node that could contain our new allocation + if (NewNode !=3D NULL) { + NewNode->Allocated =3D TRUE; + NewNode->Allocation =3D (VOID*)(UINTN)NewNode->Base; + *Allocation =3D NewNode->Allocation; + mFreedBufferSize -=3D NewNode->Pages * EFI_PAGE_SIZE; + return EFI_SUCCESS; + } + + // + // Otherwise, we need to allocate a new buffer + // + + // We do not want to over-allocate in case the alignment requirement doe= s not + // require extra pages + if (Alignment > EFI_PAGE_SIZE) { + AlignmentMask =3D Alignment - 1; + Pages +=3D EFI_SIZE_TO_PAGES (Alignment); + } else { + AlignmentMask =3D 0; + } + + Status =3D gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Mem= ory); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D gDS->GetMemorySpaceDescriptor (Memory, &Descriptor); + if (!EFI_ERROR (Status)) { + // We are making an assumption that all of memory has the same default= attributes + gAttributes =3D Descriptor.Attributes; + } else { + gBS->FreePages (Memory, Pages); + return Status; + } + + Status =3D gDS->SetMemorySpaceAttributes (Memory, EFI_PAGES_TO_SIZE (Pag= es), EFI_MEMORY_WC); + if (EFI_ERROR (Status)) { + gBS->FreePages (Memory, Pages); + return Status; + } + + InvalidateDataCacheRange ((VOID *)(UINTN)Memory, EFI_PAGES_TO_SIZE (Page= s)); + + NewNode =3D AllocatePool (sizeof (FREE_PAGE_NODE)); + if (NewNode =3D=3D NULL) { + ASSERT (FALSE); + gBS->FreePages (Memory, Pages); + return EFI_OUT_OF_RESOURCES; + } + + NewNode->Base =3D Memory; + NewNode->Allocation =3D (VOID*)(((UINTN)Memory + AlignmentMask) & ~Align= mentMask); + NewNode->Pages =3D Pages; + NewNode->Allocated =3D TRUE; + NewNode->MemoryType =3D MemoryType; + + InsertTailList (&mPageList, &NewNode->Link); + + *Allocation =3D NewNode->Allocation; + return EFI_SUCCESS; +} + +/** + * Free the memory allocation + * + * This function will actually try to find the allocation in the linked li= st. + * And it will then mark the entry as freed. + * + * @param Allocation Base address of the buffer to free + * + * @return EFI_SUCCESS The allocation has been freed + * @return EFI_NOT_FOUND The allocation was not found in the pool. + * @return EFI_INVALID_PARAMETER If Allocation is NULL + * + */ +STATIC +EFI_STATUS +FreePagesFromList ( + IN VOID *Allocation + ) +{ + LIST_ENTRY *Link; + FREE_PAGE_NODE *Node; + + if (Allocation =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + for (Link =3D mPageList.ForwardLink; Link !=3D &mPageList; Link =3D Link= ->ForwardLink) { + Node =3D BASE_CR (Link, FREE_PAGE_NODE, Link); + if ((UINTN)Node->Allocation =3D=3D (UINTN)Allocation) { + Node->Allocated =3D FALSE; + + // Update the size of the freed buffer + mFreedBufferSize +=3D Node->Pages * EFI_PAGE_SIZE; + + // If the size of the non-allocated reaches the threshold we raise a= warning. + // It might be an expected behaviour in some cases. + // We might device to free some of these buffers later on. + if (mFreedBufferSize > PcdGet64 (PcdArmFreeUncachedMemorySizeThresho= ld)) { + DEBUG ((EFI_D_WARN, "Warning: The list of non-allocated buffer has= reach the threshold.\n")); + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + * This function is automatically invoked when the driver exits + * It frees all the non-allocated memory buffer. + * This function is not responsible to free allocated buffer (eg: case of = memory leak, + * runtime allocation). + */ +EFI_STATUS +EFIAPI +UncachedMemoryAllocationLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + LIST_ENTRY *Link; + FREE_PAGE_NODE *OldNode; + + // Test if the list is empty + Link =3D mPageList.ForwardLink; + if (Link =3D=3D &mPageList) { + return EFI_SUCCESS; + } + + // Free all the pages and nodes + do { + OldNode =3D BASE_CR (Link, FREE_PAGE_NODE, Link); + // Point to the next entry + Link =3D Link->ForwardLink; + + // We only free the non-allocated buffer + if (OldNode->Allocated =3D=3D FALSE) { + gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)OldNode->Base, OldNode-= >Pages); + RemoveEntryList (&OldNode->Link); + FreePool (OldNode); + } + } while (Link !=3D &mPageList); + + return EFI_SUCCESS; +} + +/** + Converts a cached or uncached address to a physical address suitable for= use in SoC registers. + + @param VirtualAddress The pointer to convert. + + @return The physical address of the supplied virtual pointer. + +**/ +EFI_PHYSICAL_ADDRESS +ConvertToPhysicalAddress ( + IN VOID *VirtualAddress + ) +{ + return (EFI_PHYSICAL_ADDRESS)(UINTN)VirtualAddress; +} + + +VOID * +UncachedInternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + return UncachedInternalAllocateAlignedPages (MemoryType, Pages, EFI_PAGE= _SIZE); +} + + +VOID * +EFIAPI +UncachedAllocatePages ( + IN UINTN Pages + ) +{ + return UncachedInternalAllocatePages (EfiBootServicesData, Pages); +} + +VOID * +EFIAPI +UncachedAllocateRuntimePages ( + IN UINTN Pages + ) +{ + return UncachedInternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +VOID * +EFIAPI +UncachedAllocateReservedPages ( + IN UINTN Pages + ) +{ + return UncachedInternalAllocatePages (EfiReservedMemoryType, Pages); +} + + + +VOID +EFIAPI +UncachedFreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + UncachedFreeAlignedPages (Buffer, Pages); + return; +} + + +VOID * +UncachedInternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + VOID *Allocation; + + if (Pages =3D=3D 0) { + return NULL; + } + + Allocation =3D NULL; + Status =3D AllocatePagesFromList (MemoryType, Pages, Alignment, &Allocat= ion); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return NULL; + } else { + return Allocation; + } +} + + +VOID +EFIAPI +UncachedFreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + FreePagesFromList (Buffer); +} + + +VOID * +UncachedInternalAllocateAlignedPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *AlignedAddress; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) =3D=3D 0); + + if (Alignment < EFI_PAGE_SIZE) { + Alignment =3D EFI_PAGE_SIZE; + } + + AlignedAddress =3D UncachedInternalAllocateAlignedPages (PoolType, EFI_S= IZE_TO_PAGES (AllocationSize), Alignment); + if (AlignedAddress =3D=3D NULL) { + return NULL; + } + + return (VOID *) AlignedAddress; +} + +VOID * +EFIAPI +UncachedAllocateAlignedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPool (EfiBootServicesData, Allocat= ionSize, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedRuntimePool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPool (EfiRuntimeServicesData, Allo= cationSize, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedReservedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedPool (EfiReservedMemoryType, Alloc= ationSize, Alignment); +} + +VOID * +UncachedInternalAllocateAlignedZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *Memory; + Memory =3D UncachedInternalAllocateAlignedPool (PoolType, AllocationSize= , Alignment); + if (Memory !=3D NULL) { + Memory =3D ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +VOID * +EFIAPI +UncachedAllocateAlignedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedZeroPool (EfiBootServicesData, All= ocationSize, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedRuntimeZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedZeroPool (EfiRuntimeServicesData, = AllocationSize, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedReservedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedZeroPool (EfiReservedMemoryType, A= llocationSize, Alignment); +} + +VOID * +UncachedInternalAllocateAlignedCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + VOID *Memory; + + ASSERT (Buffer !=3D NULL); + ASSERT (AllocationSize <=3D (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory =3D UncachedInternalAllocateAlignedPool (PoolType, AllocationSize= , Alignment); + if (Memory !=3D NULL) { + Memory =3D CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +VOID * +EFIAPI +UncachedAllocateAlignedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedCopyPool (EfiBootServicesData, All= ocationSize, Buffer, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedCopyPool (EfiRuntimeServicesData, = AllocationSize, Buffer, Alignment); +} + +VOID * +EFIAPI +UncachedAllocateAlignedReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return UncachedInternalAllocateAlignedCopyPool (EfiReservedMemoryType, A= llocationSize, Buffer, Alignment); +} + +VOID +EFIAPI +UncachedFreeAlignedPool ( + IN VOID *Allocation + ) +{ + UncachedFreePages (Allocation, 0); +} + +VOID * +UncachedInternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + UINTN CacheLineLength =3D ArmDataCacheLineLength (); + return UncachedInternalAllocateAlignedPool (MemoryType, AllocationSize, = CacheLineLength); +} + +VOID * +EFIAPI +UncachedAllocatePool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocatePool (EfiBootServicesData, AllocationSize= ); +} + +VOID * +EFIAPI +UncachedAllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocatePool (EfiRuntimeServicesData, AllocationS= ize); +} + +VOID * +EFIAPI +UncachedAllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocatePool (EfiReservedMemoryType, AllocationSi= ze); +} + +VOID * +UncachedInternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory =3D UncachedInternalAllocatePool (PoolType, AllocationSize); + if (Memory !=3D NULL) { + Memory =3D ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +VOID * +EFIAPI +UncachedAllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocateZeroPool (EfiBootServicesData, Allocation= Size); +} + +VOID * +EFIAPI +UncachedAllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocateZeroPool (EfiRuntimeServicesData, Allocat= ionSize); +} + +VOID * +EFIAPI +UncachedAllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return UncachedInternalAllocateZeroPool (EfiReservedMemoryType, Allocati= onSize); +} + +VOID * +UncachedInternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer !=3D NULL); + ASSERT (AllocationSize <=3D (MAX_ADDRESS - (UINTN) Buffer + 1)); + + Memory =3D UncachedInternalAllocatePool (PoolType, AllocationSize); + if (Memory !=3D NULL) { + Memory =3D CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +VOID * +EFIAPI +UncachedAllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return UncachedInternalAllocateCopyPool (EfiBootServicesData, Allocation= Size, Buffer); +} + +VOID * +EFIAPI +UncachedAllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return UncachedInternalAllocateCopyPool (EfiRuntimeServicesData, Allocat= ionSize, Buffer); +} + +VOID * +EFIAPI +UncachedAllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return UncachedInternalAllocateCopyPool (EfiReservedMemoryType, Allocati= onSize, Buffer); +} + +VOID +EFIAPI +UncachedFreePool ( + IN VOID *Buffer + ) +{ + UncachedFreeAlignedPool (Buffer); +} + +VOID +EFIAPI +UncachedSafeFreePool ( + IN VOID *Buffer + ) +{ + if (Buffer !=3D NULL) { + UncachedFreePool (Buffer); + Buffer =3D NULL; + } +} + diff --git a/Platform/Hisilicon/HiKey/Library/UncachedMemoryAllocationLib/U= ncachedMemoryAllocationLib.inf b/Platform/Hisilicon/HiKey/Library/UncachedM= emoryAllocationLib/UncachedMemoryAllocationLib.inf new file mode 100644 index 000000000..64edc32cf --- /dev/null +++ b/Platform/Hisilicon/HiKey/Library/UncachedMemoryAllocationLib/Uncached= MemoryAllocationLib.inf @@ -0,0 +1,45 @@ +#/** @file +# +# UncachedMemoryAllocation lib that uses DXE Service to change cachabilit= y for +# a buffer. +# +# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +# +# +#**/ + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D UncachedMemoryAllocationLib + FILE_GUID =3D DC101A1A-7525-429B-84AF-EEAA630E576C + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D UncachedMemoryAllocationLib + + DESTRUCTOR =3D UncachedMemoryAllocationLibDestructor + +[Sources.common] + UncachedMemoryAllocationLib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + Platform/Hisilicon/HiKey/HiKey.dec + +[LibraryClasses] + BaseLib + ArmLib + MemoryAllocationLib + PcdLib + DxeServicesTableLib + CacheMaintenanceLib + +[Pcd] + gArmTokenSpaceGuid.PcdArmFreeUncachedMemorySizeThreshold diff --git a/Silicon/Synopsys/Usb/DwNonPci/DwNonPciUsbDxe.inf b/Silicon/Syn= opsys/Usb/DwNonPci/DwNonPciUsbDxe.inf new file mode 100644 index 000000000..0211c937f --- /dev/null +++ b/Silicon/Synopsys/Usb/DwNonPci/DwNonPciUsbDxe.inf @@ -0,0 +1,47 @@ +## @file +# +# Initialize Designware USB controller via dummy PCI device +# +# Copyright (c) 2016, Linaro, Ltd. All rights reserved.
+# Copyright (c) 2016, Jeremy Linton +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may = 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 IM= PLIED. +# +## + +[Defines] + INF_VERSION =3D 0x00010019 + BASE_NAME =3D DwNonPcieUsbDxe + FILE_GUID =3D 298e1629-54bb-4763-8c66-e43f934a555d + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D DwNonPciUsbDxeEntryPoint + +[Sources] + InitController.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.dec + +[LibraryClasses] + BaseLib + DebugLib + IoLib + NonDiscoverableDeviceRegistrationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Pcd] + gDwUsbDxeTokenSpaceGuid.PcdDwUsbBaseAddress + gDwUsbDxeTokenSpaceGuid.PcdDwUsbSysCtrlBaseAddress + +[Depex] + TRUE diff --git a/Silicon/Synopsys/Usb/DwNonPci/InitController.c b/Silicon/Synop= sys/Usb/DwNonPci/InitController.c new file mode 100644 index 000000000..832d9dcaf --- /dev/null +++ b/Silicon/Synopsys/Usb/DwNonPci/InitController.c @@ -0,0 +1,37 @@ +/** @file + Initialize Designware USB controller via dummy PCI device + + Copyright (c) 2016, Linaro, Ltd. All rights reserved.
+ Copyright (c) 2016, Jeremy Linton + + This program and the accompanying materials are licensed and made availa= ble + 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 IMP= LIED. +**/ + +#include +#include +#include +#include + +EFI_STATUS +EFIAPI +DwNonPciUsbDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + DEBUG ((EFI_D_ERROR, "DwUsbExportController \n")); + return RegisterNonDiscoverableMmioDevice ( + NonDiscoverableDeviceTypeEhci, + NonDiscoverableDeviceDmaTypeNonCoherent, + NULL, + NULL, + 1, + FixedPcdGet32 (PcdDwUsbBaseAddress), SIZE_256KB, + FixedPcdGet32 (PcdDwUsbSysCtrlBaseAddress), SIZE_8KB); +} diff --git a/Silicon/Synopsys/Usb/DwUsbDxe/ComponentName.c b/Silicon/Synops= ys/Usb/DwUsbDxe/ComponentName.c new file mode 100644 index 000000000..53a65bb9b --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbDxe/ComponentName.c @@ -0,0 +1,244 @@ +/** @file +UEFI Component Name and Name2 protocol for Designware USB driver. + +Copyright (c) 2013-2015 Intel Corporation. +Copyright (c) 2017 Jeremy Linton + +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 IMPLI= ED. + +**/ + + + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +//#include "Ohci.h" +#include "ComponentName.h" +#include "DwUsbDxe.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gOhciComponentN= ame =3D { + OhciComponentNameGetDriverName, + OhciComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gOhciComponentN= ame2 =3D { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) OhciComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) OhciComponentNameGetController= Name, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mOhciDriverNameTabl= e[] =3D { + { "eng;en", L"Designware Usb Driver" }, + { NULL, NULL } +}; + + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f a + Unicode string. If the driver specified by This has a user readable name= in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by + This and the language specified by Languag= e was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +OhciComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mOhciDriverNameTable, + DriverName, + (BOOLEAN)(This =3D=3D &gOhciComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +OhciComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + USB_OHCI_HC_DEV *OhciDev; + EFI_USB_HC_PROTOCOL *UsbHc; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle !=3D NULL) { + return EFI_UNSUPPORTED; + } + // + // Make sure this driver is currently managing ControllerHandle + // +/* Status =3D EfiTestManagedDevice ( + ControllerHandle, + gOhciDriverBinding.DriverBindingHandle, + &gEfiPciIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; +}*/ + // + // Get the device context + // + Status =3D gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbHcProtocolGuid, + (VOID **) &UsbHc, + gOhciDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + OhciDev =3D USB_OHCI_HC_DEV_FROM_THIS (UsbHc); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + OhciDev->ControllerNameTable, + ControllerName, + (BOOLEAN)(This =3D=3D &gOhciComponentName) + ); + +} diff --git a/Silicon/Synopsys/Usb/DwUsbDxe/ComponentName.h b/Silicon/Synops= ys/Usb/DwUsbDxe/ComponentName.h new file mode 100644 index 000000000..cfc660334 --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbDxe/ComponentName.h @@ -0,0 +1,148 @@ +/** @file +UEFI Component Name and Name2 protocol for Designware USB driver. + +Copyright (c) 2013-2015 Intel Corporation. +Copyright (c) 2017 Jeremy Linton + +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 IMPLI= ED. + +**/ + +#ifndef _COMPONENT_NAME_H_ +#define _COMPONENT_NAME_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 o= f a + Unicode string. If the driver specified by This has a user readable name= in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by + This and the language specified by Languag= e was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +OhciComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +OhciComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +#endif + diff --git a/Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.c b/Silicon/Synopsys/Us= b/DwUsbDxe/DwUsbDxe.c new file mode 100644 index 000000000..6903112f9 --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.c @@ -0,0 +1,2324 @@ +/** @file + + Copyright (c) 2015, Linaro Limited. All rights reserved. + Copyright (c) 2015, Hisilicon Limited. All rights reserved. + Copyright (c) 2017, Jeremy Linton. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DwUsbDxe.h" +#include "Hi6220.h" + +// Blah, the existing hikey driver only works in OTG mode (aka its an endp= oint device for fastboot) +// out of the box this driver configures a made up protocol which +// setups the port to act as a fastboot programming taget. This sucks! +#ifdef NOTACTIVE + +STATIC dwc_otg_dev_dma_desc_t *g_dma_desc,*g_dma_desc_ep0,*g_dma_desc_in; +STATIC USB_DEVICE_REQUEST *p_ctrlreq; +STATIC VOID *rx_buf; +STATIC UINT32 rx_desc_bytes =3D 0; +STATIC UINTN mNumDataBytes; + +#define USB_BLOCK_HIGH_SPEED_SIZE 512 +#define DATA_SIZE 32768 +#define CMD_SIZE 512 +#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) = - 1) + + + +STATIC USB_DEVICE_DESCRIPTOR *mDeviceDescriptor; + +// The config descriptor, interface descriptor, and endpoint descriptors i= n a +// buffer (in that order) +STATIC VOID *mDescriptors; +// Convenience pointers to those descriptors inside the buffer: +STATIC USB_INTERFACE_DESCRIPTOR *mInterfaceDescriptor; +STATIC USB_CONFIG_DESCRIPTOR *mConfigDescriptor; +STATIC USB_ENDPOINT_DESCRIPTOR *mEndpointDescriptors; + +STATIC USB_DEVICE_RX_CALLBACK mDataReceivedCallback; +STATIC USB_DEVICE_TX_CALLBACK mDataSentCallback; + +STATIC EFI_USB_STRING_DESCRIPTOR mLangStringDescriptor =3D { + 4, + USB_DESC_TYPE_STRING, + {0x409} +}; + + +// The time between interrupt polls, in units of 100 nanoseconds +// 10 Microseconds +#define DW_INTERRUPT_POLL_PERIOD 10000 +STATIC int usb_drv_port_speed(void) /*To detect which mode was run, high s= peed or full speed*/ +{ + /* + * 2'b00: High speed (PHY clock is running at 30 or 60 MHz) + */ + UINT32 val =3D READ_REG32(DSTS) & 2; + return (!val); +} + + + +STATIC VOID reset_endpoints(void) +{ + /* EP0 IN ACTIVE NEXT=3D1 */ + WRITE_REG32(DIEPCTL0, 0x8800); + + /* EP0 OUT ACTIVE */ + WRITE_REG32(DOEPCTL0, 0x8000); + + /* Clear any pending OTG Interrupts */ + WRITE_REG32(GOTGINT, 0xFFFFFFFF); + + /* Clear any pending interrupts */ + WRITE_REG32(GINTSTS, 0xFFFFFFFF); + WRITE_REG32(DIEPINT0, 0xFFFFFFFF); + WRITE_REG32(DOEPINT0, 0xFFFFFFFF); + WRITE_REG32(DIEPINT1, 0xFFFFFFFF); + WRITE_REG32(DOEPINT1, 0xFFFFFFFF); + + /* IN EP interrupt mask */ + WRITE_REG32(DIEPMSK, 0x0D); + /* OUT EP interrupt mask */ + WRITE_REG32(DOEPMSK, 0x0D); + /* Enable interrupts on Ep0 */ + WRITE_REG32(DAINTMSK, 0x00010001); + + /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to rec= eive setup packet*/ + WRITE_REG32(DOEPTSIZ0, 0x60080040); + + //notes that:the compulsive conversion is expectable. + g_dma_desc_ep0->status.b.bs =3D 0x3; + g_dma_desc_ep0->status.b.mtrf =3D 0; + g_dma_desc_ep0->status.b.sr =3D 0; + g_dma_desc_ep0->status.b.l =3D 1; + g_dma_desc_ep0->status.b.ioc =3D 1; + g_dma_desc_ep0->status.b.sp =3D 0; + g_dma_desc_ep0->status.b.bytes =3D 64; + g_dma_desc_ep0->buf =3D (UINT32)(UINTN)(p_ctrlreq); + g_dma_desc_ep0->status.b.sts =3D 0; + g_dma_desc_ep0->status.b.bs =3D 0x0; + WRITE_REG32(DOEPDMA0, (unsigned long)(g_dma_desc_ep0)); + /* EP0 OUT ENABLE CLEARNAK */ + WRITE_REG32(DOEPCTL0, (READ_REG32(DOEPCTL0) | 0x84000000)); +} + +STATIC VOID ep_tx(IN UINT8 ep, CONST VOID *ptr, UINT32 len) +{ + UINT32 blocksize; + UINT32 packets; + + /* EPx OUT ACTIVE */ + WRITE_REG32(DIEPCTL(ep), (READ_REG32(DIEPCTL(ep))) | 0x8000); + if(!ep) { + blocksize =3D 64; + } else { + blocksize =3D usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 6= 4; + } + packets =3D (len + blocksize - 1) / blocksize; + + if (!len) { //send a null packet + /* one empty packet */ + g_dma_desc_in->status.b.bs =3D 0x3; + g_dma_desc_in->status.b.l =3D 1; + g_dma_desc_in->status.b.ioc =3D 1; + g_dma_desc_in->status.b.sp =3D 1; + g_dma_desc_in->status.b.bytes =3D 0; + g_dma_desc_in->buf =3D 0; + g_dma_desc_in->status.b.sts =3D 0; + g_dma_desc_in->status.b.bs =3D 0x0; + + WRITE_REG32(DIEPDMA(ep), (unsigned long)(g_dma_desc_in)); = // DMA Address (DMAAddr) is zero + } else { //prepare to send a packet + /*WRITE_REG32((len | (packets << 19)), DIEPTSIZ(ep));*/ // packet= s+transfer size + WRITE_REG32(DIEPTSIZ(ep), len | (packets << 19)); + + //flush cache + WriteBackDataCacheRange ((void*)ptr, len); + + g_dma_desc_in->status.b.bs =3D 0x3; + g_dma_desc_in->status.b.l =3D 1; + g_dma_desc_in->status.b.ioc =3D 1; + g_dma_desc_in->status.b.sp =3D 1; + g_dma_desc_in->status.b.bytes =3D len; + g_dma_desc_in->buf =3D (UINT32)((UINTN)ptr); + g_dma_desc_in->status.b.sts =3D 0; + g_dma_desc_in->status.b.bs =3D 0x0; + WRITE_REG32(DIEPDMA(ep), (unsigned long)(g_dma_desc_in)); = // ptr is DMA address + } + asm("dsb sy"); + asm("isb sy"); + /* epena & cnak*/ + WRITE_REG32(DIEPCTL(ep), READ_REG32(DIEPCTL(ep)) | 0x84000800); + return; +} + +STATIC VOID ep_rx(unsigned ep, UINT32 len) +{ + /* EPx UNSTALL */ + WRITE_REG32(DOEPCTL(ep), ((READ_REG32(DOEPCTL(ep))) & (~0x00200000))); + /* EPx OUT ACTIVE */ + WRITE_REG32(DOEPCTL(ep), (READ_REG32(DOEPCTL(ep)) | 0x8000)); + + if (len >=3D DATA_SIZE) + rx_desc_bytes =3D DATA_SIZE; + else + rx_desc_bytes =3D len; + + rx_buf =3D AllocatePool (DATA_SIZE); + ASSERT (rx_buf !=3D NULL); + + InvalidateDataCacheRange (rx_buf, len); + + g_dma_desc->status.b.bs =3D 0x3; + g_dma_desc->status.b.mtrf =3D 0; + g_dma_desc->status.b.sr =3D 0; + g_dma_desc->status.b.l =3D 1; + g_dma_desc->status.b.ioc =3D 1; + g_dma_desc->status.b.sp =3D 0; + g_dma_desc->status.b.bytes =3D rx_desc_bytes; + g_dma_desc->buf =3D (UINT32)((UINTN)rx_buf); + g_dma_desc->status.b.sts =3D 0; + g_dma_desc->status.b.bs =3D 0x0; + + asm("dsb sy"); + asm("isb sy"); + WRITE_REG32(DOEPDMA(ep), (UINT32)((UINTN)g_dma_desc)); + /* EPx OUT ENABLE CLEARNAK */ + WRITE_REG32(DOEPCTL(ep), (READ_REG32(DOEPCTL(ep)) | 0x84000000)); +} + +STATIC +EFI_STATUS +HandleGetDescriptor ( + IN USB_DEVICE_REQUEST *Request + ) +{ + UINT8 DescriptorType; + UINTN ResponseSize; + VOID *ResponseData; +// CHAR16 SerialNo[16]; +// UINTN SerialNoLen; +// EFI_STATUS Status; + + ResponseSize =3D 0; + ResponseData =3D NULL; + + // Pretty confused if bmRequestType is anything but this: + ASSERT (Request->RequestType =3D=3D USB_DEV_GET_DESCRIPTOR_REQ_TYPE); + + // Choose the response + DescriptorType =3D Request->Value >> 8; + switch (DescriptorType) { + case USB_DESC_TYPE_DEVICE: + DEBUG ((EFI_D_ERROR, "USB: Got a request for device descriptor\n")); + ResponseSize =3D sizeof (USB_DEVICE_DESCRIPTOR); + ResponseData =3D mDeviceDescriptor; + break; + case USB_DESC_TYPE_CONFIG: + DEBUG ((EFI_D_ERROR, "USB: Got a request for config descriptor\n")); + ResponseSize =3D mConfigDescriptor->TotalLength; + ResponseData =3D mDescriptors; + break; + case USB_DESC_TYPE_STRING: + DEBUG ((EFI_D_ERROR, "USB: Got a request for String descriptor %d\n", = Request->Value & 0xFF)); + switch (Request->Value & 0xff) { + case 0: + ResponseSize =3D mLangStringDescriptor.Length; + ResponseData =3D &mLangStringDescriptor; + break; + case 1: + ResponseSize =3D mManufacturerStringDescriptor.Hdr.Length; + ResponseData =3D &mManufacturerStringDescriptor; + break; + case 2: + ResponseSize =3D mProductStringDescriptor.Hdr.Length; + ResponseData =3D &mProductStringDescriptor; + break; + case 3: +/* Status =3D gRT->GetVariable ( + (CHAR16*)L"SerialNo", + &gArmGlobalVariableGuid, + NULL, + &SerialNoLen, + SerialNo + ); + if (EFI_ERROR (Status) =3D=3D 0) { + CopyMem (mSerialStringDescriptor.String, SerialNo, SerialNoLen); + } + ResponseSize =3D mSerialStringDescriptor.Length; + ResponseData =3D &mSerialStringDescriptor;*/ + CopyMem (mSerialStringDescriptor.Hdr.String, "12345", 6); + ResponseSize =3D 6; + ResponseData =3D &mSerialStringDescriptor; + + break; + } + break; + default: + DEBUG ((EFI_D_ERROR, "USB: Didn't understand request for descriptor 0x= %04x\n", Request->Value)); + break; + } + + // Send the response + if (ResponseData) { + ASSERT (ResponseSize !=3D 0); + + if (Request->Length < ResponseSize) { + // Truncate response + ResponseSize =3D Request->Length; + } else if (Request->Length > ResponseSize) { + DEBUG ((EFI_D_ERROR, "USB: Info: ResponseSize < wLength\n")); + } + + ep_tx(0, ResponseData, ResponseSize); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +HandleSetAddress ( + IN USB_DEVICE_REQUEST *Request + ) +{ + // Pretty confused if bmRequestType is anything but this: + ASSERT (Request->RequestType =3D=3D USB_DEV_SET_ADDRESS_REQ_TYPE); + DEBUG ((EFI_D_ERROR, "USB: Setting address to %d\n", Request->Value)); + reset_endpoints(); + + WRITE_REG32(DCFG, (READ_REG32(DCFG) & ~0x7F0) | (Request->Value << 4)); + ep_tx(0, 0, 0); + + return EFI_SUCCESS; +} + +int usb_drv_request_endpoint(unsigned int type, int dir) +{ + unsigned int ep =3D 1; /*FIXME*/ + int ret; + unsigned long newbits; + =20 + ret =3D (int)ep | dir; + newbits =3D (type << 18) | 0x10000000; + =20 + /* + * (type << 18):Endpoint Type (EPType) + * 0x10000000:Endpoint Enable (EPEna) + * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control. + * (ep<<22):TxFIFO Number (TxFNum) + * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes o= n this endpoint. + */ + if (dir) { // IN: to host + WRITE_REG32(DIEPCTL(ep), ((READ_REG32(DIEPCTL(ep)))& ~0x000C0000) | new= bits | (ep<<22)|0x20000); + } else { // OUT: to device + WRITE_REG32(DOEPCTL(ep), ((READ_REG32(DOEPCTL(ep))) & ~0x000C0000) | ne= wbits); + } + =20 + return ret; +} +STATIC +EFI_STATUS +HandleSetConfiguration ( + IN USB_DEVICE_REQUEST *Request + ) +{ + ASSERT (Request->RequestType =3D=3D USB_DEV_SET_CONFIGURATION_REQ_TYPE); + + // Cancel all transfers + reset_endpoints(); + + usb_drv_request_endpoint(2, 0); + usb_drv_request_endpoint(2, 0x80); + + WRITE_REG32(DIEPCTL1, (READ_REG32(DIEPCTL1)) | 0x10088800); + + /* Enable interrupts on all endpoints */ + WRITE_REG32(DAINTMSK, 0xFFFFFFFF); + + ep_rx(1, CMD_SIZE); + ep_tx(0, 0, 0); + return EFI_SUCCESS; +} + + +STATIC +EFI_STATUS +HandleDeviceRequest ( + IN USB_DEVICE_REQUEST *Request + ) +{ + EFI_STATUS Status; + + switch (Request->Request) { + case USB_DEV_GET_DESCRIPTOR: + Status =3D HandleGetDescriptor (Request); + break; + case USB_DEV_SET_ADDRESS: + Status =3D HandleSetAddress (Request); + break; + case USB_DEV_SET_CONFIGURATION: + Status =3D HandleSetConfiguration (Request); + break; + default: + DEBUG ((EFI_D_ERROR, + "Didn't understand RequestType 0x%x Request 0x%x\n", + Request->RequestType, Request->Request)); + Status =3D EFI_INVALID_PARAMETER; + break; + } + + return Status; +} + + +// Instead of actually registering interrupt handlers, we poll the control= ler's +// interrupt source register in this function. +STATIC +VOID +CheckInterrupts ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 ints =3D READ_REG32(GINTSTS); // interrupt register + UINT32 epints; + + /* + * bus reset + * The core sets this bit to indicate that a reset is detected on the US= B. + */ + if (ints & 0x1000) { + WRITE_REG32(DCFG, 0x800004); + reset_endpoints(); + } + + /* + * enumeration done, we now know the speed + * The core sets this bit to indicate that speed enumeration is complete= . The + * application must read the Device Status (DSTS) register to obtain the + * enumerated speed. + */ + if (ints & 0x2000) { + /* Set up the maximum packet sizes accordingly */ + unsigned long maxpacket =3D usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED= _SIZE : 64; + //Set Maximum In Packet Size (MPS) + WRITE_REG32(DIEPCTL1, ((READ_REG32(DIEPCTL1)) & ~0x000003FF) | maxpacke= t); + //Set Maximum Out Packet Size (MPS) + WRITE_REG32(DOEPCTL1, ((READ_REG32(DOEPCTL1)) & ~0x000003FF) | maxpacke= t); + } + + /* + * IN EP event + * The core sets this bit to indicate that an interrupt is pending on on= e of the IN + * endpoints of the core (in Device mode). The application must read the + * Device All Endpoints Interrupt (DAINT) register to determine the exact + * number of the IN endpoint on which the interrupt occurred, and then r= ead + * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register = to + * determine the exact cause of the interrupt. The application must clea= r the + * appropriate status bit in the corresponding DIEPINTn register to clea= r this bit. + */ + if (ints & 0x40000) { + epints =3D READ_REG32(DIEPINT0); + WRITE_REG32(DIEPINT0, epints); + if (epints & 0x1) /* Transfer Completed Interrupt (XferCompl) */ + DEBUG ((EFI_D_ERROR, "INT: IN TX completed.DIEPTSIZ(0) =3D 0x%x.\n", R= EAD_REG32(DIEPTSIZ0))); + + epints =3D READ_REG32(DIEPINT1); + WRITE_REG32(DIEPINT1, epints); + if (epints & 0x1) + DEBUG ((EFI_D_ERROR, "ep1: IN TX completed\n")); + } + + /* + * OUT EP event + * The core sets this bit to indicate that an interrupt is pending on on= e of the + * OUT endpoints of the core (in Device mode). The application must read= the + * Device All Endpoints Interrupt (DAINT) register to determine the exact + * number of the OUT endpoint on which the interrupt occurred, and then = read + * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register + * to determine the exact cause of the interrupt. The application must c= lear the + * appropriate status bit in the corresponding DOEPINTn register to clea= r this bit. + */ + if (ints & 0x80000) { + /* indicates the status of an endpoint + * with respect to USB- and AHB-related events. */ + epints =3D READ_REG32(DOEPINT0); + if(epints) { + WRITE_REG32(DOEPINT0, epints); + if (epints & 0x1) + DEBUG ((EFI_D_ERROR,"INT: EP0 RX completed. DOEPTSIZ(0) =3D 0x%x.\n",= READ_REG32(DOEPTSIZ0))); + /* + * + IN Token Received When TxFIFO is Empty (INTknTXFEmp) + * Indicates that an IN token was received when the associated TxFIFO = (periodic/nonperiodic) + * was empty. This interrupt is asserted on the endpoint for which the= IN token + * was received. + */ + if (epints & 0x8) { /* SETUP phase done */ + // PRINT_DEBUG("Setup phase \n"); + WRITE_REG32(DIEPCTL0, READ_REG32(DIEPCTL0) | 0x08000000); + WRITE_REG32(DOEPCTL0, READ_REG32(DOEPCTL0) | 0x08000000); + /*clear IN EP intr*/ + WRITE_REG32(DIEPINT0, 0xffffffff); + HandleDeviceRequest((USB_DEVICE_REQUEST *)p_ctrlreq); + } + + /* Make sure EP0 OUT is set up to accept the next request */ + /* memset(p_ctrlreq, 0, NUM_ENDPOINTS*8); */ + WRITE_REG32(DOEPTSIZ0, 0x60080040); + /* + * IN Token Received When TxFIFO is Empty (INTknTXFEmp) + * Indicates that an IN token was received when the associated TxFIFO = (periodic/nonperiodic) + * was empty. This interrupt is asserted on the endpoint for which the= IN token + * was received. + */ + g_dma_desc_ep0->status.b.bs =3D 0x3; + g_dma_desc_ep0->status.b.mtrf =3D 0; + g_dma_desc_ep0->status.b.sr =3D 0; + g_dma_desc_ep0->status.b.l =3D 1; + g_dma_desc_ep0->status.b.ioc =3D 1; + g_dma_desc_ep0->status.b.sp =3D 0; + g_dma_desc_ep0->status.b.bytes =3D 64; + g_dma_desc_ep0->buf =3D (UINT32)(UINTN)(p_ctrlreq); + g_dma_desc_ep0->status.b.sts =3D 0; + g_dma_desc_ep0->status.b.bs =3D 0x0; + WRITE_REG32(DOEPDMA0, (unsigned long)(g_dma_desc_ep0)); + // endpoint enable; clear NAK + WRITE_REG32(DOEPCTL0, 0x84000000); + } + + epints =3D (READ_REG32(DOEPINT1)); + if(epints) { + WRITE_REG32(DOEPINT1, epints); + /* Transfer Completed Interrupt (XferCompl);Transfer completed */ + if (epints & 0x1) { + asm("dsb sy"); + asm("isb sy"); + + UINT32 bytes =3D rx_desc_bytes - g_dma_desc->status.b.bytes; + UINT32 len =3D 0; + + if (MATCH_CMD_LITERAL ("download", rx_buf)) { + mNumDataBytes =3D AsciiStrHexToUint64 (rx_buf + sizeof ("download")); + } else { + if (mNumDataBytes !=3D 0) + mNumDataBytes -=3D bytes; + } + + mDataReceivedCallback (bytes, rx_buf); + + if (mNumDataBytes =3D=3D 0) + len =3D CMD_SIZE; + else if (mNumDataBytes > DATA_SIZE) + len =3D DATA_SIZE; + else + len =3D mNumDataBytes; + + ep_rx(1, len); + } + } + } + + //WRITE_REG32 clear ints + WRITE_REG32(GINTSTS, ints); +} + +EFI_STATUS +DwUsbSend ( + IN UINT8 EndpointIndex, + IN UINTN Size, + IN CONST VOID *Buffer + ) +{ + ep_tx(EndpointIndex, Buffer, Size); + return 0; +} + + +STATIC VOID usb_init() +{ + VOID* buf; + + buf =3D UncachedAllocatePages (1); + g_dma_desc =3D buf; + g_dma_desc_ep0 =3D g_dma_desc + sizeof(struct dwc_otg_dev_dma_desc); + g_dma_desc_in =3D g_dma_desc_ep0 + sizeof(struct dwc_otg_dev_dma_desc); + p_ctrlreq =3D (USB_DEVICE_REQUEST *)g_dma_desc_in + sizeof(struct dwc_ot= g_dev_dma_desc); + + SetMem(g_dma_desc, sizeof(struct dwc_otg_dev_dma_desc), 0); + SetMem(g_dma_desc_ep0, sizeof(struct dwc_otg_dev_dma_desc), 0); + SetMem(g_dma_desc_in, sizeof(struct dwc_otg_dev_dma_desc), 0); + + /*Reset usb controller.*/ + /* Wait for AHB master idle */ + while (!((READ_REG32(GRSTCTL)) & 0x80000000)); + + /* OTG: Assert Software Reset */ + WRITE_REG32(GRSTCTL, 1); + + /* Wait for OTG to ack reset */ + while ((READ_REG32(GRSTCTL)) & 1); + + /* Wait for OTG AHB master idle */ + while (!((READ_REG32(GRSTCTL)) & 0x80000000)); + + WRITE_REG32(GDFIFOCFG, DATA_FIFO_CONFIG); + WRITE_REG32(GRXFSIZ, RX_SIZE); + WRITE_REG32(GNPTXFSIZ, ENDPOINT_TX_SIZE); + WRITE_REG32(DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1); + + /* + * set Periodic TxFIFO Empty Level, + * Non-Periodic TxFIFO Empty Level, + * Enable DMA, Unmask Global Intr + */ + WRITE_REG32(GAHBCFG, 0x1a1); + + /*select 8bit UTMI+, ULPI Inerface*/ + WRITE_REG32(GUSBCFG, 0x2400); + + /* Detect usb work mode,host or device? */ + while ((READ_REG32(GINTSTS)) & 1); + MicroSecondDelay(1); + + /*Init global and device mode csr register.*/ + /*set Non-Zero-Length status out handshake */ + WRITE_REG32(DCFG, 0x800004); + + /* Interrupt unmask: IN event, OUT event, bus reset */ + WRITE_REG32(GINTMSK, 0xC3C08); + + while ((READ_REG32(GINTSTS)) & 0x2000); + + /* Clear any pending OTG Interrupts */ + WRITE_REG32(GOTGINT, 0xFFFFFFFF); + /* Clear any pending interrupts */ + WRITE_REG32(GINTSTS, 0xFFFFFFFF); + WRITE_REG32(GINTMSK, 0xFFFFFFFF); + WRITE_REG32(GOTGINT, READ_REG32(GOTGINT) & (~0x3000)); + /*endpoint settings cfg*/ + reset_endpoints(); + + /*init finish. and ready to transfer data*/ + + /* Soft Disconnect */ + WRITE_REG32(DCTL, 0x802); + MicroSecondDelay(1); + + /* Soft Reconnect */ + WRITE_REG32(DCTL, 0x800); +} + + + +EFI_STATUS +EFIAPI +DwUsbStart ( + IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor, + IN VOID **Descriptors, + IN USB_DEVICE_RX_CALLBACK RxCallback, + IN USB_DEVICE_TX_CALLBACK TxCallback + ) +{ + UINT8 *Ptr; + EFI_STATUS Status; + EFI_EVENT TimerEvent; + + ASSERT (DeviceDescriptor !=3D NULL); + ASSERT (Descriptors[0] !=3D NULL); + ASSERT (RxCallback !=3D NULL); + ASSERT (TxCallback !=3D NULL); + + usb_init(); + + mDeviceDescriptor =3D DeviceDescriptor; + mDescriptors =3D Descriptors[0]; + + // Right now we just support one configuration + ASSERT (mDeviceDescriptor->NumConfigurations =3D=3D 1); + // ... and one interface + mConfigDescriptor =3D (USB_CONFIG_DESCRIPTOR *)mDescriptors; + ASSERT (mConfigDescriptor->NumInterfaces =3D=3D 1); + + Ptr =3D ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR); + mInterfaceDescriptor =3D (USB_INTERFACE_DESCRIPTOR *) Ptr; + Ptr +=3D sizeof (USB_INTERFACE_DESCRIPTOR); + + mEndpointDescriptors =3D (USB_ENDPOINT_DESCRIPTOR *) Ptr; + + mDataReceivedCallback =3D RxCallback; + mDataSentCallback =3D TxCallback; + + // Register a timer event so CheckInterupts gets called periodically + Status =3D gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + CheckInterrupts, + NULL, + &TimerEvent + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D gBS->SetTimer ( + TimerEvent, + TimerPeriodic, + DW_INTERRUPT_POLL_PERIOD + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +USB_DEVICE_PROTOCOL mUsbDevice =3D { + DwUsbStart, + DwUsbSend +}; + + + + +#endif + + +STATIC VOID phy_init(USB_OHCI_HC_DEV *Ehc) +{ + UINT32 val; + + DEBUG ((EFI_D_ERROR, "phy_init() sequence\n")); + // setup direction of hub + val =3D GPIO_READ_REG32(GPIODIR); + DEBUG ((EFI_D_ERROR, "GPIO0_3=3D%X DIR=3D%X CTL=3D%X\n", GPIO_READ_REG32= (GPIODATA_3),val,GPIO_READ_REG32(GPIOAFSEL))); + val |=3D 0x84; + GPIO_WRITE_REG32(GPIODIR,val); + + + asm("dsb sy"); + asm("isb sy"); + MicroSecondDelay (1000);=20 + GPIO_WRITE_REG32(GPIODATA_3,1<<3); + GPIO_WRITE_REG32(GPIODATA_7,1<<7); + + asm("dsb sy"); + asm("isb sy"); + MicroSecondDelay (1000);=20 + DEBUG ((EFI_D_ERROR, "GPIO0_3=3D%X DIR=3D%X CTL=3D%X\n", GPIO_READ_REG32= (GPIODATA_3),val,GPIO_READ_REG32(GPIOAFSEL))); + DEBUG ((EFI_D_ERROR, "GPIO0=3D%X\n", GPIO_READ_REG32(0x3FC))); +// DEBUG ((EFI_D_ERROR, "GPIO0_7=3D%X\n", GPIO_READ_REG32(GPIODATA_7))); = //turn on Hub port +/* ++STATIC ++VOID ++HiKeyDetectUsbModeInit ( ++ IN VOID ++ ) ++{ ++ EFI_STATUS Status; ++ ++ //set pullup on both GPIO2_5 & GPIO2_6. It's required for inupt.=20 ++ MmioWrite32 (0xf8001864, 1); ++ MmioWrite32 (0xf8001868, 1); ++ ++ Status =3D gBS->LocateProtocol (&gEmbeddedGpioProtocolGuid, NULL, (VOID= **)&mGpio); ++ ASSERT_EFI_ERROR (Status); ++ Status =3D mGpio->Set (mGpio, USB_SEL_GPIO0_3, GPIO_MODE_OUTPUT_0); ++ ASSERT_EFI_ERROR (Status); ++ Status =3D mGpio->Set (mGpio, USB_5V_HUB_EN, GPIO_MODE_OUTPUT_0); ++ ASSERT_EFI_ERROR (Status); ++ MicroSecondDelay (1000); ++ ++ Status =3D mGpio->Set (mGpio, USB_ID_DET_GPIO2_5, GPIO_MODE_INPUT); ++ ASSERT_EFI_ERROR (Status); ++ Status =3D mGpio->Set (mGpio, USB_VBUS_DET_GPIO2_6, GPIO_MODE_INPUT); ++ ASSERT_EFI_ERROR (Status); ++} */ + + //setup clock + val =3D PHY_READ_REG32(SC_PERIPH_CLKEN0); + val |=3D BIT4; + PHY_WRITE_REG32(SC_PERIPH_CLKEN0, val); + + do { + val =3D PHY_READ_REG32(SC_PERIPH_CLKSTAT0); + } while ((val & BIT4) =3D=3D 0); + + // setup phy (this is just hi6220_phy_init() minus the "reset enable"? + // AKA looks like its just pulling the phy out of reset + val =3D PHY_READ_REG32(SC_PERIPH_RSTDIS0); + val |=3D RST0_USBOTG_BUS | RST0_POR_PICOPHY | RST0_USBOTG | RST0_USBOTG= _32K; + PHY_WRITE_REG32(SC_PERIPH_RSTDIS0, val); + + // this is the "on" mode from linux hi6220_phy_setup() + val =3D PHY_READ_REG32(SC_PERIPH_CTRL5); + val &=3D ~CTRL5_PICOPHY_BC_MODE; + val |=3D CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB; //newer HIsi edk h= as this | CTRL5_PICOPHY_VDATDETENB | CTRL5_PICOPHY_DCDENB; ; + PHY_WRITE_REG32(SC_PERIPH_CTRL5, val); + + val =3D PHY_READ_REG32(SC_PERIPH_CTRL4); + val &=3D ~(CTRL4_PICO_SIDDQ | CTRL4_PICO_OGDISABLE); + val |=3D CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL | CTRL4_OTG_= PHY_SEL; + PHY_WRITE_REG32(SC_PERIPH_CTRL4, val); + + PHY_WRITE_REG32(SC_PERIPH_CTRL8, EYE_PATTERN_PARA); +} + +// Try to get the controller inited, the appropriate linux function +// is probably dwc2_core_host_init() +STATIC VOID DwHostInit(USB_OHCI_HC_DEV *Ehc) +{ + UINT32 reg; + + // rpi needs the USB controller powered? + // do we? + // play with PCGCCTL=20 +/* status =3D dwc_power_on(); + if (status !=3D USB_STATUS_SUCCESS) + { + return status; + }*/ + + DEBUG ((EFI_D_ERROR, "DwHostInit reset\n")); + /*Reset usb controller.*/ + /* Wait for AHB master idle */ + while (!((READ_REG32(GRSTCTL)) & GRSTCTL_AHBIDLE)); + /* Assert Software Reset */ + WRITE_REG32(GRSTCTL, GRSTCTL_CSFTRST); + /* Wait for ack reset */ + while ((READ_REG32(GRSTCTL)) & GRSTCTL_CSFTRST); + /* Wait for AHB master idle */ + while (!((READ_REG32(GRSTCTL)) & GRSTCTL_AHBIDLE)); + + // version + reg=3DREAD_REG32(GSNPSID); //global rx fifo size + DEBUG ((EFI_D_ERROR, "DwHostInit version %X\n",reg)); + + DEBUG ((EFI_D_ERROR, "DwHostInit setup dma\n")); + reg=3DREAD_REG32(GRXFSIZ); //global rx fifo size + DEBUG ((EFI_D_ERROR, "DwHostInit global rx fifo size 0x%X\n",reg)); + reg=3DREAD_REG32(GNPTXFSIZ); //global np tx fifo size + DEBUG ((EFI_D_ERROR, "DwHostInit global np tx fifo size 0x%X\n",reg)); + reg=3DREAD_REG32(HPTXFSIZ); //global tx fifo size + DEBUG ((EFI_D_ERROR, "DwHostInit global tx fifo size 0x%X\n",reg)); + reg=3DREAD_REG32(GNPTXSTS); //global np tx fifo status + DEBUG ((EFI_D_ERROR, "DwHostInit global np tx fifo status 0x%X\n",reg)); + + reg=3DREAD_REG32(GAHBCFG); + DEBUG ((EFI_D_ERROR, "DwHostInit global AHB config 0x%X\n",reg)); + reg |=3D GAHBCFG_DMA_EN; + WRITE_REG32(GAHBCFG, reg); +=09 +// dwc_soft_reset(); +// dwc_setup_dma_mode(); +// dwc_setup_interrupts(); +// status =3D dwc_start_xfer_scheduler(); +/* if (status !=3D USB_STATUS_SUCCESS) + { + dwc_power_off(); + }*/ +} + +// Compare with dwc2_hc_init() +// Can we get away with just using a single channel? +// after all, we only want sync request/response type=20 +// behavior.... +STATIC EFI_STATUS DwChannelInit(USB_OHCI_HC_DEV *Ehc, int DevAddr, int EpN= um, EFI_USB_DATA_DIRECTION EpDir, BOOLEAN Slow, UINT8 Type, UINT8 MaxPacket) +{ + UINT32 hcchar; + int channel =3D 0; + hcchar =3D DevAddr << HCCHAR_DEVADDR_SHIFT & HCCHAR_DEVADDR_MASK; + hcchar |=3D EpNum << HCCHAR_EPNUM_SHIFT & HCCHAR_EPNUM_MASK; + hcchar |=3D Type << HCCHAR_EPTYPE_SHIFT & HCCHAR_EPTYPE_MASK; + hcchar |=3D MaxPacket << HCCHAR_MPS_SHIFT & HCCHAR_MPS_MASK; + + if (EpDir =3D=3D EfiUsbDataIn) { + hcchar |=3D HCCHAR_EPDIR; + } + if (Slow) { + hcchar |=3D HCCHAR_LSPDDEV; + } + hcchar |=3D (READ_REG32(HFNUM) +1) & 1; //set odd frame??? + hcchar |=3D HCCHAR_CHENA; // enable channel, disable is already cleared + + WRITE_REG32(HCINT(channel), 0); //clear existing channel stat= us + WRITE_REG32(HCINTMSK(channel), 0xFFFFFFFF); //enable all status flags + WRITE_REG32(HCCHAR(channel), hcchar); + + return EFI_SUCCESS; +} + + + +/** + Provides software reset for the USB host controller. + + @param This This EFI_USB_HC_PROTOCOL instance. + @param Attributes A bit mask of the reset operation to perfo= rm. + + @retval EFI_SUCCESS The reset operation succeeded. + @retval EFI_INVALID_PARAMETER Attributes is not valid. + @retval EFI_UNSUPPOURTED The type of reset specified by Attributes = is + not currently supported by the host contro= ller. + @retval EFI_DEVICE_ERROR Host controller isn't halted to reset. + +**/ +EFI_STATUS +EFIAPI +OhciReset ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT16 Attributes + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciReset\n")); + return EFI_SUCCESS; +} + +/** + Retrieve the current state of the USB host controller. + + @param This This EFI_USB_HC_PROTOCOL instance. + @param State Variable to return the current host contro= ller + state. + + @retval EFI_SUCCESS Host controller state was returned in Stat= e. + @retval EFI_INVALID_PARAMETER State is NULL. + @retval EFI_DEVICE_ERROR An error was encountered while attempting = to + retrieve the host controller's current sta= te. + +**/ + +EFI_STATUS +EFIAPI +OhciGetState ( + IN EFI_USB_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciGetState\n")); + return EFI_SUCCESS; +} + +/** + Sets the USB host controller to a specific state. + + @param This This EFI_USB_HC_PROTOCOL instance. + @param State The state of the host controller that will= be set. + + @retval EFI_SUCCESS The USB host controller was successfully p= laced + in the state specified by State. + @retval EFI_INVALID_PARAMETER State is invalid. + @retval EFI_DEVICE_ERROR Failed to set the state due to device erro= r. + +**/ + +EFI_STATUS +EFIAPI +OhciSetState( + IN EFI_USB_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciSetState\n")); + return EFI_SUCCESS; +} + +/** + + Submits control transfer to a target USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL insta= nce. + @param DeviceAddress Represents the address of the target devic= e on the USB, + which is assigned during USB enumeration. + @param IsSlowDevice Indicates whether the target device is slo= w device + or full-speed device. + @param MaxPaketLength Indicates the maximum packet size that the + default control transfer endpoint is capab= le of + sending or receiving. + @param Request A pointer to the USB device request that w= ill be sent + to the USB device. + @param TransferDirection Specifies the data direction for the trans= fer. + There are three values available, DataIn, = DataOut + and NoData. + @param Data A pointer to the buffer of data that will = be transmitted + to USB device or received from USB device. + @param DataLength Indicates the size, in bytes, of the data = buffer + specified by Data. + @param TimeOut Indicates the maximum time, in microsecond= s, + which the transfer is allowed to complete. + @param TransferResult A pointer to the detailed result informati= on generated + by this control transfer. + + @retval EFI_SUCCESS The control transfer was completed success= fully. + @retval EFI_OUT_OF_RESOURCES The control transfer could not be complete= d due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The control transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The control transfer failed due to host co= ntroller or device error. + Caller should check TranferResult for deta= iled error information. + +--*/ + +void DumpRequest(EFI_USB_DEVICE_REQUEST *Request) +{ + if (Request->RequestType & 0x80) { + DEBUG ((EFI_D_ERROR, "USB: RequestType %X -> Host\n",Request->RequestTyp= e)); + } + else { + DEBUG ((EFI_D_ERROR, "USB: RequestType %X -> Device\n",Request->RequestT= ype)); + } + if (Request->RequestType & 0x60) { + DEBUG ((EFI_D_ERROR, "USB: -> CLS/VEND\n")); + } + else { + DEBUG ((EFI_D_ERROR, "USB: -> STD\n")); + } + switch (Request->RequestType & 0x03) { + case USB_TARGET_DEVICE: + DEBUG ((EFI_D_ERROR, "USB: -> DEVICE\n")); + break; + case USB_TARGET_INTERFACE: + DEBUG ((EFI_D_ERROR, "USB: -> ITERFACE\n")); + break; + case USB_TARGET_ENDPOINT: + DEBUG ((EFI_D_ERROR, "USB: -> ENDPOINT\n")); + break; + case USB_TARGET_OTHER: + DEBUG ((EFI_D_ERROR, "USB: -> OTHER\n")); + break; + } + DEBUG ((EFI_D_ERROR, "USB: RequestType 0x%X\n",Request->RequestType)); + switch (Request->Request) { + case USB_DEV_GET_STATUS: + DEBUG ((EFI_D_ERROR, "USB: GET STATUS\n")); + break; + case USB_DEV_CLEAR_FEATURE: + DEBUG ((EFI_D_ERROR, "USB: CLEAR FEATURE\n")); + break; + case USB_DEV_SET_FEATURE: + DEBUG ((EFI_D_ERROR, "USB: SET FEATURE\n")); + break; + case USB_DEV_SET_ADDRESS: + DEBUG ((EFI_D_ERROR, "USB: SET ADDRESS\n")); + break; + case USB_DEV_GET_DESCRIPTOR: + DEBUG ((EFI_D_ERROR, "USB: GET DESCRIPTOR\n")); + break; + case USB_DEV_SET_DESCRIPTOR: + DEBUG ((EFI_D_ERROR, "USB: SET DESCRIPTOR\n")); + break; + default: + break; + } + DEBUG ((EFI_D_ERROR, "USB: Request %d\n",Request->Request)); + DEBUG ((EFI_D_ERROR, "USB: Value 0x%X\n",Request->Value)); + DEBUG ((EFI_D_ERROR, "USB: Index 0x%X\n",Request->Index)); + DEBUG ((EFI_D_ERROR, "USB: Length %d\n",Request->Length)); +} + +STATIC USB_DEVICE_DESCRIPTOR RootDevDescriptor =3D=20 +{ + .Length =3D sizeof(USB_DEVICE_DESCRIPTOR), + .DescriptorType =3D USB_DESC_TYPE_DEVICE, + .BcdUSB =3D 0x200, + .DeviceClass =3D 0x09, //TYPE HUB + .DeviceSubClass =3D 0, + .DeviceProtocol =3D 1, + .MaxPacketSize0 =3D 18, + .IdVendor =3D 0, + .IdProduct =3D 2, + .BcdDevice =3D 0, + .StrManufacturer =3D 0, + .StrProduct =3D 1, + .StrSerialNumber =3D 2, + .NumConfigurations =3D 1 +}; + +STATIC struct ROOT_HUB_CFG=20 +{ + USB_CONFIG_DESCRIPTOR RootCfgDescriptor; + USB_INTERFACE_DESCRIPTOR RootIntDescriptor; + USB_ENDPOINT_DESCRIPTOR RootEndDescriptor; +} RootCfg =3D +{ + .RootCfgDescriptor =3D + { + .Length =3D sizeof(USB_CONFIG_DESCRIPTOR), + .DescriptorType =3D USB_DESC_TYPE_CONFIG, + .TotalLength =3D sizeof(struct ROOT_HUB_CFG), + .NumInterfaces =3D 1, + .ConfigurationValue =3D 1, + .Configuration =3D 0 , + .Attributes =3D 0xC0, + .MaxPower =3D 0 + }, + .RootIntDescriptor =3D=20 + { + .Length =3D sizeof(USB_INTERFACE_DESCRIPTOR), + .DescriptorType =3D USB_DESC_TYPE_INTERFACE, + .InterfaceNumber =3D 0, + .AlternateSetting =3D 0, + .NumEndpoints =3D 1, + .InterfaceClass =3D 0x09, //hub + .InterfaceSubClass =3D 0, + .InterfaceProtocol =3D 0, + .Interface =3D 0 + }, + .RootEndDescriptor =3D=20 + { + .Length =3D sizeof(USB_ENDPOINT_DESCRIPTOR), + .DescriptorType =3D USB_DESC_TYPE_ENDPOINT, + .EndpointAddress =3D 0x81, + .Attributes =3D 0x03, + .MaxPacketSize =3D 64, + .Interval =3D 0xFF + }, +}; + +typedef struct { + EFI_USB_STRING_DESCRIPTOR Hdr; + CHAR16 buf[16]; +} DEF_EFI_USB_STRING_DESCRIPTOR; + +STATIC DEF_EFI_USB_STRING_DESCRIPTOR mManufacturerStringDescriptor =3D { + {=20 + 18, + USB_DESC_TYPE_STRING, + {'9'} + },=20 + {'6', 'B', 'o', 'a', 'r', 'd', 's'} +}; + +STATIC DEF_EFI_USB_STRING_DESCRIPTOR mProductStringDescriptor =3D { + { + 12, + USB_DESC_TYPE_STRING, + {'H'} + },=20 + {'i', 'K', 'e', 'y'} +}; + +STATIC DEF_EFI_USB_STRING_DESCRIPTOR mSerialStringDescriptor =3D { + { + 34, + USB_DESC_TYPE_STRING, + {'0'} + }, + {'1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'} +}; + + + + +EFI_STATUS +EFIAPI +OhciControlTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaxPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +{ + int handled =3D 0; + static int first =3D 1; +#define ENABLE_EMULATION 20 + DEBUG ((EFI_D_ERROR, "USB: OhciControlTransfer (addr:%d) (direction:%d) = Len:%d\n",DeviceAddress,TransferDirection,*DataLength)); + + DumpRequest(Request); + if ((DeviceAddress =3D=3D 0+ENABLE_EMULATION) && (first)) + { + // ignore first set addr + first =3D 0; + handled =3D 1; + DEBUG ((EFI_D_ERROR, "USB: OhciControlTransfer, ignore first set addr = for root port\n")); + } + if (DeviceAddress =3D=3D 1+ENABLE_EMULATION) { //root port fake response + if (Request->RequestType =3D=3D 0x80) { //device to host + if (Request->Request =3D=3D USB_DEV_GET_DESCRIPTOR) { + DEBUG ((EFI_D_ERROR, "USB: OhciControlTransfer get descriptor\n")); + if ((Request->Value & 0xFF) =3D=3D 0) + { + switch (Request->Value >> 8) { + case USB_DESC_TYPE_DEVICE: + CopyMem (Data, &RootDevDescriptor, *DataLength); + handled =3D 1; + break; + case USB_DESC_TYPE_CONFIG: + CopyMem (Data, &RootCfg, *DataLength); + handled =3D 1; + break; + case USB_DESC_TYPE_STRING: + switch (Request->Index) + { + case 0: + CopyMem (Data, &mManufacturerStringDescriptor, *DataLength); + handled =3D 1; + break; + case 1: + CopyMem (Data, &mProductStringDescriptor, *DataLength); + handled =3D 1; + break; + case 2: + CopyMem (Data, &mSerialStringDescriptor, *DataLength); + handled =3D 1; + break; + + } + break; + } + } + } + } + if (Request->RequestType =3D=3D 0) //host to device + { + if (Request->Request =3D=3D USB_DEV_SET_CONFIGURATION) + { + DEBUG ((EFI_D_ERROR, "USB: OhciControlTransfer Set configuration\n")); + handled =3D 1; + } + } + } + + if (!handled) { + USB_OHCI_HC_DEV *Ehc; + UINT64 addr;=20 + UINT32 transfer; + + EFI_PHYSICAL_ADDRESS BusPhysAddr; + UINTN BusLength; + VOID *Mapping; + EFI_STATUS Status; + + + DEBUG ((EFI_D_ERROR, "USB: OhciControlTransfer forward to (slow=3D%d) (M= axTransfer=3D%d) bus\n",IsSlowDevice,MaxPacketLength)); + Ehc =3D USB_OHCI_HC_DEV_FROM_THIS (This); + + BusLength =3D sizeof(EFI_USB_DEVICE_REQUEST); + Status =3D Ehc->PciIo->Map(Ehc->PciIo, EfiPciIoOperationBusMasterRead, R= equest, &BusLength, &BusPhysAddr, &Mapping); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Usb: Map DMA failed\n")); + } + + addr =3D BusPhysAddr; + DEBUG ((EFI_D_ERROR, "USB: OhciControlTransfer 1 DMAADDR=3D%X BUSADDR=3D= %X\n",Request,addr)); + // Ek gad, really? Split each control transfer into its phases? (see dwc= 2_hc_init_xfer) + // SETUP->DATA->STATUS +// ASSERT(Request<32bit); + WRITE_REG32(HCDMA(0), (UINT32)addr); + transfer =3D TSIZ_SC_MC_PID_SETUP<PciIo->Unmap (Ehc->PciIo, Mapping); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Usb: failed to Unmap DMA\n")); + } + + + // word aligned buffer can go directly to HCDMA + // packet count =3D 1, send 'Request' + // wait for complete packet + if (*DataLength) + { + // do the data phase. + BusLength =3D *DataLength; + Mapping =3D NULL; + Status =3D Ehc->PciIo->Map(Ehc->PciIo, EfiPciIoOperationBusMasterCommo= nBuffer , Data, &BusLength, &BusPhysAddr, &Mapping); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Usb: Map DMA failed\n")); + } + =09 + addr =3D BusPhysAddr; + +// addr=3D(UINT64)Data; + DEBUG ((EFI_D_ERROR, "USB: OhciControlTransfer 6 datap=3D%X\n",addr)); + WRITE_REG32(HCDMA(0), (UINT32)addr); + transfer =3D TSIZ_SC_MC_PID_DATA0<PciIo->Unmap (Ehc->PciIo, Mapping); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Usb: failed to Unmap DMA\n")); + } + + } + + // do the status phase + // status flows in the oposite direction of data + if (TransferDirection =3D=3D EfiUsbDataIn) { + TransferDirection =3D EfiUsbDataOut; + } + else { + TransferDirection =3D EfiUsbDataIn; + } + + *TransferResult=3D0; + + BusLength =3D 4; + Status =3D Ehc->PciIo->Map(Ehc->PciIo, EfiPciIoOperationBusMasterWrite ,= TransferResult , &BusLength, &BusPhysAddr, &Mapping); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Usb: Map DMA failed\n")); + } + =09 + addr =3D BusPhysAddr; + +// addr=3D(UINT64)TransferResult; + WRITE_REG32(HCDMA(0), (UINT32)addr); + transfer =3D TSIZ_SC_MC_PID_DATA1<PciIo->Unmap (Ehc->PciIo, Mapping); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Usb: failed to Unmap DMA\n")); + } + + DEBUG ((EFI_D_ERROR, "USB: OhciControlTransfer Status =3D %X pkt_remaini= ng =3D %d \n",READ_REG32(HCINT(0)), READ_REG32(HCTSIZ(0)))); + DEBUG ((EFI_D_ERROR, "USB: OhciControlTransfer Status =3D %X tdata =3D%X= \n",READ_REG32(HCINT(0)),*TransferResult )); + // packet count =3D DataLength/Maxpacket (+1) send/recv 'Data' + // wait from complete + // (other direction for status) + //DwChannelInit(Ehc, DeviceAddress, 0 , TransferDirection, IsSlowDevice,= USB_ENDPOINT_XFER_CONTROL, MaxPacketLength); + } + + return EFI_SUCCESS; +} + + +/** + + Submits bulk transfer to a bulk endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL insta= nce. + @param DeviceAddress Represents the address of the target devic= e on the USB, + which is assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and = an + endpoint direction of the target USB devic= e. + Each endpoint address supports data transf= er in + one direction except the control endpoint + (whose default endpoint address is 0). + It is the caller's responsibility to make = sure that + the EndPointAddress represents a bulk endp= oint. + @param MaximumPacketLength Indicates the maximum packet size the targ= et endpoint + is capable of sending or receiving. + @param Data A pointer to the buffer of data that will = be transmitted + to USB device or received from USB device. + @param DataLength When input, indicates the size, in bytes, = of the data buffer + specified by Data. When output, indicates = the actually + transferred data size. + @param DataToggle A pointer to the data toggle value. On inp= ut, it indicates + the initial data toggle value the bulk tra= nsfer should adopt; + on output, it is updated to indicate the d= ata toggle value + of the subsequent bulk transfer. + @param TimeOut Indicates the maximum time, in microsecond= s, which the + transfer is allowed to complete. + TransferResult A pointer to the detailed result informati= on of the + bulk transfer. + + @retval EFI_SUCCESS The bulk transfer was completed successful= ly. + @retval EFI_OUT_OF_RESOURCES The bulk transfer could not be submitted d= ue to lack of resource. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The bulk transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The bulk transfer failed due to host contr= oller or device error. + Caller should check TranferResult for deta= iled error information. + +**/ + + +EFI_STATUS +EFIAPI +OhciBulkTransfer( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaxPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciBulkTransfer\n")); + return EFI_SUCCESS; +} + + +/** + + Submits an interrupt transfer to an interrupt endpoint of a USB device. + + @param Ohc Device private data + @param DeviceAddress Represents the address of the target devic= e on the USB, + which is assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and = an endpoint + direction of the target USB device. Each e= ndpoint address + supports data transfer in one direction ex= cept the + control endpoint (whose default endpoint a= ddress is 0). + It is the caller's responsibility to make = sure that + the EndPointAddress represents an interrup= t endpoint. + @param IsSlowDevice Indicates whether the target device is slo= w device + or full-speed device. + @param MaxPacketLength Indicates the maximum packet size the targ= et endpoint + is capable of sending or receiving. + @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is= built between + the host and the target interrupt endpoint. + If FALSE, the specified asynchronous inter= rupt pipe + is canceled. + @param DataToggle A pointer to the data toggle value. On in= put, it is valid + when IsNewTransfer is TRUE, and it indicat= es the initial + data toggle value the asynchronous interru= pt transfer + should adopt. + On output, it is valid when IsNewTransfer = is FALSE, + and it is updated to indicate the data tog= gle value of + the subsequent asynchronous interrupt tran= sfer. + @param PollingInterval Indicates the interval, in milliseconds, t= hat the + asynchronous interrupt transfer is polled. + This parameter is required when IsNewTrans= fer is TRUE. + @param UCBuffer Uncacheable buffer + @param DataLength Indicates the length of data to be receive= d at the + rate specified by PollingInterval from the= target + asynchronous interrupt endpoint. This par= ameter + is only required when IsNewTransfer is TRU= E. + @param CallBackFunction The Callback function.This function is cal= led at the + rate specified by PollingInterval.This par= ameter is + only required when IsNewTransfer is TRUE. + @param Context The context that is passed to the CallBack= Function. + This is an optional parameter and may be N= ULL. + @param IsPeriodic Periodic interrupt or not + @param OutputED The correspoding ED carried out + @param OutputTD The correspoding TD carried out + + + @retval EFI_SUCCESS The asynchronous interrupt transfer reques= t has been successfully + submitted or canceled. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to = a lack of resources. + +**/ + +EFI_STATUS +OhciInterruptTransfer ( + IN USB_OHCI_HC_DEV *Ohc, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaxPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle OPTIONAL, + IN UINTN PollingInterval OPTIONAL, + IN VOID *UCBuffer OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL, + IN VOID *Context OPTIONAL, + IN BOOLEAN IsPeriodic OPTIONAL, + OUT VOID **OutputED OPTIONAL, + OUT VOID **OutputTD OPTIONAL + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciInterruptTransfer\n")); + return EFI_SUCCESS; +} + +/** + + Submits an asynchronous interrupt transfer to an interrupt endpoint of a= USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL insta= nce. + @param DeviceAddress Represents the address of the target devic= e on the USB, + which is assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and = an endpoint + direction of the target USB device. Each e= ndpoint address + supports data transfer in one direction ex= cept the + control endpoint (whose default endpoint a= ddress is 0). + It is the caller's responsibility to make = sure that + the EndPointAddress represents an interrup= t endpoint. + @param IsSlowDevice Indicates whether the target device is slo= w device + or full-speed device. + @param MaxiumPacketLength Indicates the maximum packet size the targ= et endpoint + is capable of sending or receiving. + @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is= built between + the host and the target interrupt endpoint. + If FALSE, the specified asynchronous inter= rupt pipe + is canceled. + @param DataToggle A pointer to the data toggle value. On in= put, it is valid + when IsNewTransfer is TRUE, and it indicat= es the initial + data toggle value the asynchronous interru= pt transfer + should adopt. + On output, it is valid when IsNewTransfer = is FALSE, + and it is updated to indicate the data tog= gle value of + the subsequent asynchronous interrupt tran= sfer. + @param PollingInterval Indicates the interval, in milliseconds, t= hat the + asynchronous interrupt transfer is polled. + This parameter is required when IsNewTrans= fer is TRUE. + @param DataLength Indicates the length of data to be receive= d at the + rate specified by PollingInterval from the= target + asynchronous interrupt endpoint. This par= ameter + is only required when IsNewTransfer is TRU= E. + @param CallBackFunction The Callback function.This function is cal= led at the + rate specified by PollingInterval.This par= ameter is + only required when IsNewTransfer is TRUE. + @param Context The context that is passed to the CallBack= Function. + This is an optional parameter and may be N= ULL. + + @retval EFI_SUCCESS The asynchronous interrupt transfer reques= t has been successfully + submitted or canceled. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to = a lack of resources. + +**/ + + +EFI_STATUS +EFIAPI +OhciAsyncInterruptTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaxPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle OPTIONAL, + IN UINTN PollingInterval OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL, + IN VOID *Context OPTIONAL + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciAsyncInterruptTransfer\n")); + return EFI_SUCCESS; +} + +/** + + Submits synchronous interrupt transfer to an interrupt endpoint + of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL insta= nce. + @param DeviceAddress Represents the address of the target devic= e on the USB, + which is assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and = an endpoint + direction of the target USB device. Each e= ndpoint + address supports data transfer in one dire= ction + except the control endpoint (whose default + endpoint address is 0). It is the caller's= responsibility + to make sure that the EndPointAddress repr= esents + an interrupt endpoint. + @param IsSlowDevice Indicates whether the target device is slo= w device + or full-speed device. + @param MaxPacketLength Indicates the maximum packet size the targ= et endpoint + is capable of sending or receiving. + @param Data A pointer to the buffer of data that will = be transmitted + to USB device or received from USB device. + @param DataLength On input, the size, in bytes, of the data = buffer specified + by Data. On output, the number of bytes tr= ansferred. + @param DataToggle A pointer to the data toggle value. On inp= ut, it indicates + the initial data toggle value the synchron= ous interrupt + transfer should adopt; + on output, it is updated to indicate the d= ata toggle value + of the subsequent synchronous interrupt tr= ansfer. + @param TimeOut Indicates the maximum time, in microsecond= s, which the + transfer is allowed to complete. + @param TransferResult A pointer to the detailed result informati= on from + the synchronous interrupt transfer. + + @retval EFI_UNSUPPORTED This interface not available. + @retval EFI_INVALID_PARAMETER Parameters not follow spec + +**/ + + +EFI_STATUS +EFIAPI +OhciSyncInterruptTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaxPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciSyncInterruptTransfer\n")); + return EFI_SUCCESS; +} + +/** + + Submits isochronous transfer to a target USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL insta= nce. + @param DeviceAddress Represents the address of the target devic= e on the USB, + which is assigned during USB enumeration. + @param EndPointAddress End point address + @param MaximumPacketLength Indicates the maximum packet size that the + default control transfer endpoint is capab= le of + sending or receiving. + @param Data A pointer to the buffer of data that will = be transmitted + to USB device or received from USB device. + @param DataLength Indicates the size, in bytes, of the data = buffer + specified by Data. + @param TransferResult A pointer to the detailed result informati= on generated + by this control transfer. + + @retval EFI_UNSUPPORTED This interface not available + @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or Transfe= rResult is NULL + +**/ + + +EFI_STATUS +EFIAPI +OhciIsochronousTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN DataLength, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciIsochronousTransfer\n")); + if (Data =3D=3D NULL || DataLength =3D=3D 0 || TransferResult =3D=3D NUL= L) { + return EFI_INVALID_PARAMETER; + } + + return EFI_UNSUPPORTED; +} + + +/** + + Submits Async isochronous transfer to a target USB device. + + @param his A pointer to the EFI_USB_HC_PROTOCOL insta= nce. + @param DeviceAddress Represents the address of the target devic= e on the USB, + which is assigned during USB enumeration. + @param EndPointAddress End point address + @param MaximumPacketLength Indicates the maximum packet size that the + default control transfer endpoint is capab= le of + sending or receiving. + @param Data A pointer to the buffer of data that will = be transmitted + to USB device or received from USB device. + @param IsochronousCallBack When the transfer complete, the call back = function will be called + @param Context Pass to the call back function as parameter + + @retval EFI_UNSUPPORTED This interface not available + @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0 + +**/ + +EFI_STATUS +EFIAPI +OhciAsyncIsochronousTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciAsyncIsochronousTransfer\n")); + if (Data =3D=3D NULL || DataLength =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + + return EFI_UNSUPPORTED; +} + +/** + + Retrieves the number of root hub ports. + + @param This A pointer to the EFI_USB_HC_PROTOCOL insta= nce. + @param NumOfPorts A pointer to the number of the root hub po= rts. + + @retval EFI_SUCCESS The port number was retrieved successfully. +**/ +EFI_STATUS +EFIAPI +OhciGetRootHubNumOfPorts ( + IN EFI_USB_HC_PROTOCOL *This, + OUT UINT8 *NumOfPorts + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciGetRootHubNumOfPorts\n")); + //TODO, so apparently this devices root port can't be probed? + // default to one port, and simulate it? + *NumOfPorts =3D 1; + return EFI_SUCCESS; +} + +#define MAXPORTS 4; + +/** + + Retrieves the current status of a USB root hub port. + + @param This A pointer to the EFI_USB_HC_PROTOCOL. + @param PortNumber Specifies the root hub port from which the= status + is to be retrieved. This value is zero-ba= sed. For example, + if a root hub has two ports, then the firs= t port is numbered 0, + and the second port is numbered 1. + @param PortStatus A pointer to the current port status bits = and + port status change bits. + + @retval EFI_SUCCESS The status of the USB root hub port specif= ied by PortNumber + was returned in PortStatus. + @retval EFI_INVALID_PARAMETER Port number not valid +**/ + + +EFI_STATUS +EFIAPI +OhciGetRootHubPortStatus ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +{ + USB_OHCI_HC_DEV *Ehc; + +// DEBUG ((EFI_D_ERROR, "USB: OhciGetRootHubPortStatus %d\n",PortNumber)); + if (PortStatus =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Ehc =3D USB_OHCI_HC_DEV_FROM_THIS (This); + + //TODO more faked status? + // The HPRT register contains the host status + // indicating speed/power etc + PortStatus->PortStatus =3D 0; + PortStatus->PortChangeStatus =3D 0; + PortStatus->PortStatus |=3D USB_PORT_STAT_LOW_SPEED; + PortStatus->PortStatus |=3D USB_PORT_STAT_ENABLE; + PortStatus->PortStatus |=3D USB_PORT_STAT_POWER; + PortStatus->PortStatus |=3D USB_PORT_STAT_CONNECTION; + + // on first status (reset/whatever) describe a new connection + if (Ehc->PortStatus) { + DEBUG ((EFI_D_ERROR, "USB: OhciGetRootHubPortStatus %d change to connect= ed\n",PortNumber)); + DEBUG ((EFI_D_ERROR, "USB: OhciGetRootHubPortStatus actual hport status = %X\n",READ_REG32(HPRT))); + Ehc->PortStatus =3D 0; + PortStatus->PortChangeStatus |=3D USB_PORT_STAT_CONNECTION; + } + + return EFI_SUCCESS; +} + +/** + + Sets a feature for the specified root hub port. + + @param This A pointer to the EFI_USB_HC_PROTOCOL. + @param PortNumber Specifies the root hub port whose feature + is requested to be set. + @param PortFeature Indicates the feature selector associated + with the feature set request. + + @retval EFI_SUCCESS The feature specified by PortFeature was s= et for the + USB root hub port specified by PortNumber. + @retval EFI_DEVICE_ERROR Set feature failed because of hardware iss= ue + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is in= valid. +**/ +EFI_STATUS +EFIAPI +OhciSetRootHubPortFeature ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciSetRootHubPortFeature port(%d) -> %d\n",Po= rtNumber,PortFeature)); + switch (PortFeature) { + case EfiUsbPortReset: + DEBUG ((EFI_D_ERROR, "USB: OhciSetRootHubPortFeature reset\n")); + break; + case EfiUsbPortEnable: + DEBUG ((EFI_D_ERROR, "USB: OhciSetRootHubPortFeature enable\n")); + break; + default: + DEBUG ((EFI_D_ERROR, "USB: OhciSetRootHubPortFeature (other)\n")); + } + return EFI_SUCCESS; +} + + +/** + + Clears a feature for the specified root hub port. + + @param This A pointer to the EFI_USB_HC_PROTOCOL insta= nce. + @param PortNumber Specifies the root hub port whose feature + is requested to be cleared. + @param PortFeature Indicates the feature selector associated = with the + feature clear request. + + @retval EFI_SUCCESS The feature specified by PortFeature was c= leared for the + USB root hub port specified by PortNumber. + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is in= valid. + @retval EFI_DEVICE_ERROR Some error happened when clearing feature +**/ +EFI_STATUS +EFIAPI +OhciClearRootHubPortFeature ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + DEBUG ((EFI_D_ERROR, "USB: OhciClearRootHubPortFeature port(%d) -> %d\n",= PortNumber,PortFeature)); + return EFI_SUCCESS; +} + +USB_OHCI_HC_DEV * +OhciAllocateDev ( + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + USB_OHCI_HC_DEV *Ohc; +// EFI_STATUS Status; +// VOID *Buf; +// EFI_PHYSICAL_ADDRESS PhyAddr; +// VOID *Map; + UINTN Pages; + UINTN Bytes; + + Ohc =3D AllocateZeroPool (sizeof (USB_OHCI_HC_DEV)); + if (Ohc =3D=3D NULL) { + return NULL; + } + + Ohc->Signature =3D USB_DW_HC_DEV_SIGNATURE; + Ohc->PciIo =3D PciIo; + + Ohc->UsbHc.Reset =3D OhciReset; + Ohc->UsbHc.GetState =3D OhciGetState; + Ohc->UsbHc.SetState =3D OhciSetState; + Ohc->UsbHc.ControlTransfer =3D OhciControlTransfer; + Ohc->UsbHc.BulkTransfer =3D OhciBulkTransfer; + Ohc->UsbHc.AsyncInterruptTransfer =3D OhciAsyncInterruptTransfer; + Ohc->UsbHc.SyncInterruptTransfer =3D OhciSyncInterruptTransfer; + Ohc->UsbHc.IsochronousTransfer =3D OhciIsochronousTransfer; + Ohc->UsbHc.AsyncIsochronousTransfer =3D OhciAsyncIsochronousTransfer; + Ohc->UsbHc.GetRootHubPortNumber =3D OhciGetRootHubNumOfPorts; + Ohc->UsbHc.GetRootHubPortStatus =3D OhciGetRootHubPortStatus; + Ohc->UsbHc.SetRootHubPortFeature =3D OhciSetRootHubPortFeature; + Ohc->UsbHc.ClearRootHubPortFeature =3D OhciClearRootHubPortFeature; + Ohc->UsbHc.MajorRevision =3D 0x1; + Ohc->UsbHc.MinorRevision =3D 0x1; + +// Ohc->HccaMemoryBlock =3D NULL; + Ohc->HccaMemoryMapping =3D NULL; + Ohc->HccaMemoryBuf =3D NULL; + Ohc->HccaMemoryPages =3D 0; +// Ohc->InterruptContextList =3D NULL; + Ohc->ControllerNameTable =3D NULL; + Ohc->HouseKeeperTimer =3D NULL; + +/* Ohc->MemPool =3D UsbHcInitMemPool(PciIo, TRUE, 0); + if(Ohc->MemPool =3D=3D NULL) { + goto FREE_DEV_BUFFER; + }*/ + + Bytes =3D 4096; + Pages =3D EFI_SIZE_TO_PAGES (Bytes); + +/* Status =3D PciIo->AllocateBuffer ( + PciIo, + AllocateAnyPages, + EfiBootServicesData, + Pages, + &Buf, + 0 + ); + + if (EFI_ERROR (Status)) { + goto FREE_MEM_POOL; + } + + Status =3D PciIo->Map ( + PciIo, + EfiPciIoOperationBusMasterCommonBuffer, + Buf, + &Bytes, + &PhyAddr, + &Map + ); + + if (EFI_ERROR (Status) || (Bytes !=3D 4096)) { + goto FREE_MEM_PAGE; + }*/ + +// Ohc->HccaMemoryBlock =3D (HCCA_MEMORY_BLOCK *)(UINTN)PhyAddr; +// Ohc->HccaMemoryMapping =3D Map; +// Ohc->HccaMemoryBuf =3D (VOID *)(UINTN)Buf; + Ohc->HccaMemoryPages =3D Pages; + Ohc->PortStatus =3D 1; + + return Ohc; + +//FREE_MEM_PAGE: +// PciIo->FreeBuffer (PciIo, Pages, Buf); +//FREE_MEM_POOL: +// UsbHcFreeMemPool (Ohc->MemPool); +//FREE_DEV_BUFFER: +// FreePool(Ohc); + + return NULL; +} + +/** + + One notified function to stop the Host Controller when gBS->ExitBootServ= ices() called. + + @param Event Pointer to this event + @param Context Event handler private data +**/ +VOID +EFIAPI +DwHcExitBootService ( + EFI_EVENT Event, + VOID *Context + ) +{ + DEBUG ((EFI_D_ERROR, "DwUsbExitBootService!\n")); +} + + +#pragma pack(1) +typedef struct { + UINT8 ProgInterface; + UINT8 SubClassCode; + UINT8 BaseCode; +} USB_CLASSC; +#pragma pack() +//typedef struct _USB2_HC_DEV USB2_HC_DEV; + +/** + Test to see if this driver supports ControllerHandle. Any + ControllerHandle that has Usb2HcProtocol installed will + be supported. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath Not used. + + @return EFI_SUCCESS This driver supports this device. + @return EFI_UNSUPPORTED This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +DwUsbDriverBindingSupported ( + 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; + +// DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingSupported\n")); + // + // Test whether there is PCI IO Protocol attached on the controller hand= le. + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status =3D PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_CLASSCODE_OFFSET, + sizeof (USB_CLASSC) / sizeof (UINT8), + &UsbClassCReg + ); + + if (EFI_ERROR (Status)) { + Status =3D EFI_UNSUPPORTED; + goto ON_EXIT; + } + + // + // Test whether the controller belongs to Usb class type + // + if ((UsbClassCReg.BaseCode !=3D PCI_CLASS_SERIAL) || (UsbClassCReg.SubCl= assCode !=3D PCI_CLASS_SERIAL_USB)) { + Status =3D EFI_UNSUPPORTED; + } + else { + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingSupported found board!\n")); + } + +ON_EXIT: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Starting the Usb EHCI Driver. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath Not used. + + @return EFI_SUCCESS supports this device. + @return EFI_UNSUPPORTED do not support this device. + @return EFI_DEVICE_ERROR cannot be started due to device Error. + @return EFI_OUT_OF_RESOURCES cannot allocate resources. + +**/ +EFI_STATUS +EFIAPI +DwUsbDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; +// USB2_HC_DEV *Ehc; + USB_OHCI_HC_DEV *Ehc; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *HcDevicePath; + + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStart \n")); + // + // Open the PciIo Protocol, then enable the USB host controller + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStart2 \n")); + // + // Open Device Path Protocol for on USB host controller + // + HcDevicePath =3D NULL; + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &HcDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStart3 \n")); + // + // Create then install USB2_HC_PROTOCOL + // +// Ehc =3D EhcCreateUsb2Hc (PciIo, HcDevicePath, OriginalPciAttributes); +// Ehc =3D EhcCreateUsb2Hc (PciIo, HcDevicePath, 0); + Ehc =3D OhciAllocateDev(PciIo); + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStart4 \n")); + if (Ehc =3D=3D NULL) { + DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\= n")); + + Status =3D EFI_OUT_OF_RESOURCES; + goto CLOSE_PCIIO; + } + Status =3D gBS->InstallProtocolInterface ( + &Controller, +// &gEfiUsb2HcProtocolGuid, + &gEfiUsbHcProtocolGuid, + EFI_NATIVE_INTERFACE, + &Ehc->UsbHc + ); + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStart5 \n")); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC= Protocol\n")); + goto FREE_POOL; + } + // + // Start the asynchronous interrupt monitor + // +/* Status =3D gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POL= L_INTERVAL); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async int= errupt monitor\n")); + + EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); + goto UNINSTALL_USBHC; + } +*/ + // + // Create event to stop the HC when exit boot service. + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + DwHcExitBootService, + Ehc, + &gEfiEventExitBootServicesGuid, + &Ehc->ExitBootServiceEvent + ); + if (EFI_ERROR (Status)) { + goto UNINSTALL_USBHC; + } + + // + // Install the component name protocol, don't fail the start + // because of something for display. + // + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStart6 \n")); + AddUnicodeString2 ( + "eng", + gOhciComponentName.SupportedLanguages, + &Ehc->ControllerNameTable, + L"Designware Host Controller (USB 2.0)", + TRUE + ); + AddUnicodeString2 ( + "en", + gOhciComponentName2.SupportedLanguages, + &Ehc->ControllerNameTable, + L"Designware Host Controller (USB 2.0)", + FALSE + ); + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStart7 \n")); + phy_init(Ehc); //TODO these need the pci protocol so they talk to the ri= ght device... + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStart8 \n")); + DwHostInit(Ehc);=20 + +UNINSTALL_USBHC: +CLOSE_PCIIO: +FREE_POOL: + + DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller = @ %p\n", Controller)); + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStart9 \n")); + return EFI_SUCCESS; + +} + +/** + Stop this driver on ControllerHandle. Support stopping any child handles + created by this driver. + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on. + @param NumberOfChildren Number of Children in the ChildHandleBuffer. + @param ChildHandleBuffer List of handles for the children we need to= stop. + + @return EFI_SUCCESS Success. + @return EFI_DEVICE_ERROR Fail. + +**/ +EFI_STATUS +EFIAPI +DwUsbDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_USB2_HC_PROTOCOL *Usb2Hc; +// EFI_PCI_IO_PROTOCOL *PciIo; + USB_OHCI_HC_DEV *Ehc; + + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStop \n")); + // + // Test whether the Controller handler passed in is a valid + // Usb controller handle that should be supported, if not, + // return the error status directly + // + Status =3D gBS->OpenProtocol ( + Controller, +// &gEfiUsb2HcProtocolGuid, + &gEfiUsbHcProtocolGuid, + (VOID **) &Usb2Hc, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + +// Ehc =3D EHC_FROM_THIS (Usb2Hc); + Ehc =3D USB_OHCI_HC_DEV_FROM_THIS (This); +// PciIo =3D Ehc->PciIo; + + Status =3D gBS->UninstallProtocolInterface ( + Controller, +// &gEfiUsb2HcProtocolGuid, + &gEfiUsbHcProtocolGuid, + Usb2Hc + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Stop AsyncRequest Polling timer then stop the EHCI driver + // and uninstall the EHCI protocl. + // +/* gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL); + EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT); + + if (Ehc->PollTimer !=3D NULL) { + gBS->CloseEvent (Ehc->PollTimer); + } +*/ + if (Ehc->ExitBootServiceEvent !=3D NULL) { + gBS->CloseEvent (Ehc->ExitBootServiceEvent); + } +/* + EhcFreeSched (Ehc); + + if (Ehc->ControllerNameTable !=3D NULL) { + FreeUnicodeStringTable (Ehc->ControllerNameTable); + } +*/ + // + // Disable routing of all ports to EHCI controller, so all ports are=20 + // routed back to the UHCI or OHCI controller. + // + /*EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC); + + // + // Restore original PCI attributes + // + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + Ehc->OriginalPciAttributes, + NULL + ); + */ + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + FreePool (Ehc); + + return EFI_SUCCESS; +} + + + +EFI_DRIVER_BINDING_PROTOCOL +gOhciDriverBinding =3D { + DwUsbDriverBindingSupported, + DwUsbDriverBindingStart, + DwUsbDriverBindingStop, + 0x30, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +DwUsbEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + DEBUG ((EFI_D_ERROR, "DwUsbEntryPoint \n")); + return EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gOhciDriverBinding, + ImageHandle, + &gOhciComponentName, + &gOhciComponentName2 + ); +} diff --git a/Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.dec b/Silicon/Synopsys/= Usb/DwUsbDxe/DwUsbDxe.dec new file mode 100644 index 000000000..860da80bd --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.dec @@ -0,0 +1,42 @@ +#/** @file +# Framework Module Development Environment Industry Standards +# +# This Package provides headers and libraries that conform to EFI/PI Indus= try standards. +# Copyright (c) 2007, Intel Corporation. All rights reserved.
+# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.
+# Copyright (c) 2015-2017, Linaro. All rights reserved.
+# +# This program and the accompanying materials are licensed and made ava= ilable under +# the terms and conditions of the BSD License which accompanies this di= stribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR = IMPLIED. +# +#**/ + +[Defines] + DEC_SPECIFICATION =3D 0x00010019 + PACKAGE_NAME =3D DwUsbDxePkg + PACKAGE_GUID =3D 6c9afc9afb83-e3cd-4453-9b3f-78ffba3e6= 7af + PACKAGE_VERSION =3D 0.1 + + +##########################################################################= ###### +# +# Include Section - list of Include Paths that are provided by this packag= e. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_D= RIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +##########################################################################= ###### + +[Guids.common] + gDwUsbDxeTokenSpaceGuid =3D { 0x6fdd76a9, 0xf220, 0x4f1d, { 0x9c,= 0xcf, 0xbc, 0x2d, 0x68, 0x29, 0xab, 0x9d }} + +[PcdsFixedAtBuild.common] + # DwEmmc Driver PCDs + gDwUsbDxeTokenSpaceGuid.PcdDwUsbBaseAddress|0x0|UINT32|0x00000001 + gDwUsbDxeTokenSpaceGuid.PcdDwUsbSysCtrlBaseAddress|0x0|UINT32|0x0000002 diff --git a/Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.h b/Silicon/Synopsys/Us= b/DwUsbDxe/DwUsbDxe.h new file mode 100644 index 000000000..95ee0a5ee --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.h @@ -0,0 +1,534 @@ +/** @file + + Copyright (c) 2015, Linaro Limited. All rights reserved. + Copyright (c) 2015, Hisilicon Limited. All rights reserved. + Copyright (c) 2017, Jeremy Linton. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#ifndef __DW_USB_DXE_H__ +#define __DW_USB_DXE_H__ + +#define DW_USB_BASE FixedPcdGet32 (PcdDwUsbBaseAddress) +#define USB_PHY_BASE FixedPcdGet32 (PcdDwUsbSysCtrlBaseAddress) + +// This stuff is a verbatim copy of the linux phy-hi6220-usb.c driver +// Its also in the linaro hikey edk2 git tree. +// No real explanation of what these do beyond that file. +/*#define SC_PERIPH_CTRL4 0x00c + +#define CTRL4_PICO_SIDDQ BIT6 +#define CTRL4_PICO_OGDISABLE BIT8 +#define CTRL4_PICO_VBUSVLDEXT BIT10 +#define CTRL4_PICO_VBUSVLDEXTSEL BIT11 +#define CTRL4_OTG_PHY_SEL BIT21 + +#define SC_PERIPH_CTRL5 0x010 + +#define CTRL5_USBOTG_RES_SEL BIT3 +#define CTRL5_PICOPHY_ACAENB BIT4 +#define CTRL5_PICOPHY_BC_MODE BIT5 +#define CTRL5_PICOPHY_CHRGSEL BIT6 +#define CTRL5_PICOPHY_VDATSRCEND BIT7 +#define CTRL5_PICOPHY_VDATDETENB BIT8 +#define CTRL5_PICOPHY_DCDENB BIT9 +#define CTRL5_PICOPHY_IDDIG BIT10 + +#define SC_PERIPH_CTRL8 0x018 +#define SC_PERIPH_RSTEN0 0x300 +#define SC_PERIPH_RSTDIS0 0x304 + +#define RST0_USBOTG_BUS BIT4 +#define RST0_POR_PICOPHY BIT5 +#define RST0_USBOTG BIT6 +#define RST0_USBOTG_32K BIT7 + +#define EYE_PATTERN_PARA 0x7053348c*/ + +// GPIO pins to enable hub and turn on host mode +#define GPIODATA_3 0x0020 +#define GPIODATA_7 0x0200 +#define GPIODIR 0x0400 +#define GPIOAFSEL 0x0420 + +#define USB_SEL_GPIO0_3 3 // GPIO 0_3 +#define USB_5V_HUB_EN 7 // GPIO 0_7 +#define USB_ID_DET_GPIO2_5 21 // GPIO 2_5 +#define USB_VBUS_DET_GPIO2_6 22 // GPIO 2_6 +=20 + +#define PHY_READ_REG32(Offset) MmioRead32 (USB_PHY_BASE + Offset) +#define PHY_WRITE_REG32(Offset, Val) MmioWrite32 (USB_PHY_BASE + Offset, = Val) +#define GPIO_READ_REG32(Offset) MmioRead32(0xf8011000+Offset) +#define GPIO_WRITE_REG32(Offset, Val) MmioWrite32(0xf8011000+Offset,Val) + +#define READ_REG64(Offset) MmioRead64 (DW_USB_BASE + Offset) +#define READ_REG32(Offset) MmioRead32 (DW_USB_BASE + Offset) +#define READ_REG16(Offset) (UINT16) READ_REG32 (Offset) +#define WRITE_REG64(Offset, Val) MmioWrite64 (DW_USB_BASE + Offset, Val) +#define WRITE_REG32(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, Val) +#define WRITE_REG16(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT= 32) Val) +#define WRITE_REG8(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT= 32) Val) + +// Max packet size in bytes (For Full Speed USB 64 is the only valid value) +#define MAX_PACKET_SIZE_CONTROL 64 + +#define MAX_PACKET_SIZE_BULK 512 + +// 8 Endpoints, in and out. Don't count the Endpoint 0 setup buffer +#define DW_NUM_ENDPOINTS 16 + +// Endpoint Indexes +#define DW_EP0SETUP 0x20 +#define DW_EP0RX 0x00 +#define DW_EP0TX 0x01 +#define DW_EP1RX 0x02 +#define DW_EP1TX 0x03 + +// DcInterrupt bits +#define DW_DC_INTERRUPT_BRESET BIT0 +#define DW_DC_INTERRUPT_SOF BIT1 +#define DW_DC_INTERRUPT_PSOF BIT2 +#define DW_DC_INTERRUPT_SUSP BIT3 +#define DW_DC_INTERRUPT_RESUME BIT4 +#define DW_DC_INTERRUPT_HS_STAT BIT5 +#define DW_DC_INTERRUPT_DMA BIT6 +#define DW_DC_INTERRUPT_VBUS BIT7 +#define DW_DC_INTERRUPT_EP0SETUP BIT8 +#define DW_DC_INTERRUPT_EP0RX BIT10 +#define DW_DC_INTERRUPT_EP0TX BIT11 +#define DW_DC_INTERRUPT_EP1RX BIT12 +#define DW_DC_INTERRUPT_EP1TX BIT13 +// All valid peripheral controller interrupts +#define DW_DC_INTERRUPT_MASK 0x003FFFDFF + +#define DW_ADDRESS 0x200 +#define DW_ADDRESS_DEVEN BIT7 + +#define DW_MODE 0x20C +#define DW_MODE_DATA_BUS_WIDTH BIT8 +#define DW_MODE_CLKAON BIT7 +#define DW_MODE_SFRESET BIT4 +#define DW_MODE_WKUPCS BIT2 + +#define DW_ENDPOINT_MAX_PACKET_SIZE 0x204 + +#define DW_ENDPOINT_TYPE 0x208 +#define DW_ENDPOINT_TYPE_NOEMPKT BIT4 +#define DW_ENDPOINT_TYPE_ENABLE BIT3 + +#define DW_INTERRUPT_CONFIG 0x210 +// Interrupt config value to only interrupt on ACK of IN and OUT tokens +#define DW_INTERRUPT_CONFIG_ACK_ONLY BIT2 | BIT5 | BIT6 + +#define DW_DC_INTERRUPT 0x218 +#define DW_DC_INTERRUPT_ENABLE 0x214 + +#define DW_CTRL_FUNCTION 0x228 +#define DW_CTRL_FUNCTION_VENDP BIT3 +#define DW_CTRL_FUNCTION_DSEN BIT2 +#define DW_CTRL_FUNCTION_STATUS BIT1 + +#define DW_DEVICE_UNLOCK 0x27C +#define DW_DEVICE_UNLOCK_MAGIC 0xAA37 + +#define DW_SW_RESET_REG 0x30C +#define DW_SW_RESET_ALL BIT0 + +#define DW_DEVICE_ID 0x370 + +#define DW_OTG_CTRL_SET 0x374 +#define DW_OTG_CTRL_CLR OTG_CTRL_SET + 2 +#define DW_OTG_CTRL_OTG_DISABLE BIT10 +#define DW_OTG_CTRL_VBUS_CHRG BIT6 +#define DW_OTG_CTRL_VBUS_DISCHRG BIT5 +#define DW_OTG_CTRL_DM_PULLDOWN BIT2 +#define DW_OTG_CTRL_DP_PULLDOWN BIT1 +#define DW_OTG_CTRL_DP_PULLUP BIT0 + +#define DW_OTG_STATUS 0x378 +#define DW_OTG_STATUS_B_SESS_END BIT7 +#define DW_OTG_STATUS_A_B_SESS_VLD BIT1 + +#define DW_OTG_INTERRUPT_LATCH_SET 0x37C +#define DW_OTG_INTERRUPT_LATCH_CLR 0x37E +#define DW_OTG_INTERRUPT_ENABLE_RISE 0x384 + +#define DW_DMA_ENDPOINT_INDEX 0x258 + +#define DW_ENDPOINT_INDEX 0x22c +#define DW_DATA_PORT 0x220 +#define DW_BUFFER_LENGTH 0x21c + +// Device ID Values +#define PHILLIPS_VENDOR_ID_VAL 0x04cc +#define DW_PRODUCT_ID_VAL 0x1761 +#define DW_DEVICE_ID_VAL ((ISP1761_PRODUCT_ID_VAL << 16) |\ + PHILLIPS_VENDOR_ID_VAL) + +#define DWC_OTG_BASE DW_USB_BASE + +#define USB_NUM_ENDPOINTS 2 +#define MAX_EPS_CHANNELS 16 + +#define BULK_OUT_EP 1 +#define BULK_IN_EP 1 + +#define RX_REQ_LEN 512 +#define MAX_PACKET_LEN 512 + +#define DATA_FIFO_CONFIG 0x0F801000 +/* RX FIFO: 2048 bytes */ +#define RX_SIZE 0x00000200 +/* Non-periodic TX FIFO: 128 bytes. start address: 0x200 * 4. */ +#define ENDPOINT_TX_SIZE 0x01000200 + +/* EP1 TX FIFO: 1024 bytes. start address: 0x300 * 4. */ +/* EP2 TX FIFO: 1024 bytes. start address: 0x400 * 4. */ +/* EP3 TX FIFO: 1024 bytes. start address: 0x500 * 4. */ +/* EP4 TX FIFO: 1024 bytes. start address: 0x600 * 4. */ +/* EP5 TX FIFO: 1024 bytes. start address: 0x700 * 4. */ +/* EP6 TX FIFO: 1024 bytes. start address: 0x800 * 4. */ +/* EP7 TX FIFO: 1024 bytes. start address: 0x900 * 4. */ +/* EP8 TX FIFO: 1024 bytes. start address: 0xA00 * 4. */ +/* EP9 TX FIFO: 1024 bytes. start address: 0xB00 * 4. */ +/* EP10 TX FIFO: 1024 bytes. start address: 0xC00 * 4. */ +/* EP11 TX FIFO: 512 bytes. start address: 0xD00 * 4. */ +/* EP12 TX FIFO: 512 bytes. start address: 0xD80 * 4. */ +/* EP13 TX FIFO: 512 bytes. start address: 0xE00 * 4. */ +/* EP14 TX FIFO: 512 bytes. start address: 0xE80 * 4. */ +/* EP15 TX FIFO: 512 bytes. start address: 0xF00 * 4. */ + +#define DATA_IN_ENDPOINT_TX_FIFO1 0x01000300 +#define DATA_IN_ENDPOINT_TX_FIFO2 0x01000400 +#define DATA_IN_ENDPOINT_TX_FIFO3 0x01000500 +#define DATA_IN_ENDPOINT_TX_FIFO4 0x01000600 +#define DATA_IN_ENDPOINT_TX_FIFO5 0x01000700 +#define DATA_IN_ENDPOINT_TX_FIFO6 0x01000800 +#define DATA_IN_ENDPOINT_TX_FIFO7 0x01000900 +#define DATA_IN_ENDPOINT_TX_FIFO8 0x01000A00 +#define DATA_IN_ENDPOINT_TX_FIFO9 0x01000B00 +#define DATA_IN_ENDPOINT_TX_FIFO10 0x01000C00 +#define DATA_IN_ENDPOINT_TX_FIFO11 0x00800D00 +#define DATA_IN_ENDPOINT_TX_FIFO12 0x00800D80 +#define DATA_IN_ENDPOINT_TX_FIFO13 0x00800E00 +#define DATA_IN_ENDPOINT_TX_FIFO14 0x00800E80 +#define DATA_IN_ENDPOINT_TX_FIFO15 0x00800F00 + +/*DWC_OTG regsiter descriptor*/ +/*Device mode CSR MAP*/ +#define DEVICE_CSR_BASE (0x800) +/*Device mode CSR MAP*/ +#define DEVICE_INEP_BASE (0x900) +/*Device mode CSR MAP*/ +#define DEVICE_OUTEP_BASE (0xB00) + +/*** OTG LINK CORE REGISTERS ***/ +/* Core Global Registers */ +#define GOTGCTL (0x000)=20 +#define GOTGINT (0x004) +#define GAHBCFG (0x008) //Global AHB Config +#define GAHBCFG_AHB_SINGLE (1 << 23) +#define GAHBCFG_NOTI_ALL_DMA_WRIT (1 << 22) +#define GAHBCFG_REM_MEM_SUPP (1 << 21) +#define GAHBCFG_P_TXF_EMP_LVL (1 << 8) +#define GAHBCFG_NP_TXF_EMP_LVL (1 << 7) +#define GAHBCFG_DMA_EN (1 << 5) +#define GAHBCFG_HBSTLEN_MASK (0xf << 1) +#define GAHBCFG_HBSTLEN_SHIFT 1 +#define GAHBCFG_HBSTLEN_SINGLE 0 +#define GAHBCFG_HBSTLEN_INCR 1 +#define GAHBCFG_HBSTLEN_INCR4 3 +#define GAHBCFG_HBSTLEN_INCR8 5 +#define GAHBCFG_HBSTLEN_INCR16 7 +#define GAHBCFG_GLBL_INTR_EN (1 << 0) +#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \ + GAHBCFG_NP_TXF_EMP_LVL | \ + GAHBCFG_DMA_EN | \ + GAHBCFG_GLBL_INTR_EN) +#define GUSBCFG (0x00C) +#define GRSTCTL (0x010) //Global reset control +#define GRSTCTL_AHBIDLE (1 << 31) +#define GRSTCTL_DMAREQ (1 << 30) +#define GRSTCTL_TXFNUM_MASK (0x1f << 6) +#define GRSTCTL_TXFNUM_SHIFT 6 +#define GRSTCTL_TXFNUM_LIMIT 0x1f +#define GRSTCTL_TXFNUM(_x) ((_x) << 6) +#define GRSTCTL_TXFFLSH (1 << 5) +#define GRSTCTL_RXFFLSH (1 << 4) +#define GRSTCTL_IN_TKNQ_FLSH (1 << 3) +#define GRSTCTL_FRMCNTRRST (1 << 2) +#define GRSTCTL_HSFTRST (1 << 1) +#define GRSTCTL_CSFTRST (1 << 0) + +#define GINTSTS (0x014) +#define GINTMSK (0x018) +#define GRXSTSR (0x01C) +#define GRXSTSP (0x020) +#define GRXFSIZ (0x024) //Global RX FIFO Size +#define GNPTXFSIZ (0x028) //Global non periodic TX FIFO Size +#define GNPTXSTS (0x02C) //Global non periodic TX FIFO Status +#define GSNPSID (0x040) //looks like a chip version? + +#define GHWCFG1 (0x044) +#define GHWCFG2 (0x048) +#define GHWCFG3 (0x04c) +#define GHWCFG4 (0x050) +#define GLPMCFG (0x054) + +#define GDFIFOCFG (0x05c) + +#define HPTXFSIZ (0x100) +#define DIEPTXF(x) (0x100 + 4 * (x)) +#define DIEPTXF1 (0x104) +#define DIEPTXF2 (0x108) +#define DIEPTXF3 (0x10C) +#define DIEPTXF4 (0x110) +#define DIEPTXF5 (0x114) +#define DIEPTXF6 (0x118) +#define DIEPTXF7 (0x11C) +#define DIEPTXF8 (0x120) +#define DIEPTXF9 (0x124) +#define DIEPTXF10 (0x128) +#define DIEPTXF11 (0x12C) +#define DIEPTXF12 (0x130) +#define DIEPTXF13 (0x134) +#define DIEPTXF14 (0x138) +#define DIEPTXF15 (0x13C) + +/*** HOST MODE REGISTERS ***/ +/* Host Global Registers */ +#define HCFG (0x400) // host config +#define HFIR (0x404) // host frame interval +#define HFNUM (0x408) // host frame number +#define HFNUM_FRNUM_MASK (0xffff << 0)=20 +#define HPTXSTS (0x410) // host tx fifo stats +#define HAINT (0x414) // host all channels interrupt flags +#define HAINTMSK (0x418) // host all channels interrupt mask + +/* Host Port Control and Status Registers */ +#define HPRT (0x440) +#define HPRT0_SPD_MASK (0x3 << 17) +#define HPRT0_SPD_SHIFT 17 +#define HPRT0_SPD_HIGH_SPEED 0 +#define HPRT0_SPD_FULL_SPEED 1 +#define HPRT0_SPD_LOW_SPEED 2 +#define HPRT0_TSTCTL_MASK (0xf << 13) +#define HPRT0_TSTCTL_SHIFT 13 +#define HPRT0_PWR (1 << 12) +#define HPRT0_LNSTS_MASK (0x3 << 10) +#define HPRT0_LNSTS_SHIFT 10 +#define HPRT0_RST (1 << 8) +#define HPRT0_SUSP (1 << 7) +#define HPRT0_RES (1 << 6) +#define HPRT0_OVRCURRCHG (1 << 5) +#define HPRT0_OVRCURRACT (1 << 4) +#define HPRT0_ENACHG (1 << 3) +#define HPRT0_ENA (1 << 2) +#define HPRT0_CONNDET (1 << 1) +#define HPRT0_CONNSTS (1 << 0) + +/* Host Channel-Specific Registers */ +#define HCCHAR(x) (0x500 + 0x20 * (x)) //channel characteristics +#define HCCHAR_CHENA (1 << 31) // channel enable +#define HCCHAR_CHDIS (1 << 30) // channel disable +#define HCCHAR_ODDFRM (1 << 29) +#define HCCHAR_DEVADDR_MASK (0x7f << 22) +#define HCCHAR_DEVADDR_SHIFT 22 +#define HCCHAR_MULTICNT_MASK (0x3 << 20) +#define HCCHAR_MULTICNT_SHIFT 20 +#define HCCHAR_EPTYPE_MASK (0x3 << 18) +#define HCCHAR_EPTYPE_SHIFT 18 +#define HCCHAR_LSPDDEV (1 << 17) +#define HCCHAR_EPDIR (1 << 15) +#define HCCHAR_EPNUM_MASK (0xf << 11) +#define HCCHAR_EPNUM_SHIFT 11 +#define HCCHAR_MPS_MASK (0x7ff << 0) +#define HCCHAR_MPS_SHIFT 0 +#define HCSPLT(x) (0x504 + 0x20 * (x)) +#define HCINT(x) (0x508 + 0x20 * (x)) +#define HCINTMSK(x) (0x50C + 0x20 * (x)) +#define HCINTMSK_RESERVED14_31 (0x3ffff << 14) +#define HCINTMSK_FRM_LIST_ROLL (1 << 13) +#define HCINTMSK_XCS_XACT (1 << 12) +#define HCINTMSK_BNA (1 << 11) +#define HCINTMSK_DATATGLERR (1 << 10) +#define HCINTMSK_FRMOVRUN (1 << 9) +#define HCINTMSK_BBLERR (1 << 8) +#define HCINTMSK_XACTERR (1 << 7) +#define HCINTMSK_NYET (1 << 6) +#define HCINTMSK_ACK (1 << 5) +#define HCINTMSK_NAK (1 << 4) +#define HCINTMSK_STALL (1 << 3) +#define HCINTMSK_AHBERR (1 << 2) +#define HCINTMSK_CHHLTD (1 << 1) //channel halted +#define HCINTMSK_XFERCOMPL (1 << 0) +#define HCTSIZ(x) (0x510 + 0x20 * (x)) //transfer size/packet reg +#define TSIZ_DOPNG (1 << 31) //do ping before transfer +#define TSIZ_SC_MC_PID_MASK (0x3 << 29) //USB packet id +#define TSIZ_SC_MC_PID_SHIFT 29 +#define TSIZ_SC_MC_PID_DATA0 0 +#define TSIZ_SC_MC_PID_DATA2 1 +#define TSIZ_SC_MC_PID_DATA1 2 +#define TSIZ_SC_MC_PID_MDATA 3 +#define TSIZ_SC_MC_PID_SETUP 3 +#define TSIZ_PKTCNT_MASK (0x3ff << 19) +#define TSIZ_PKTCNT_SHIFT 19 +#define TSIZ_NTD_MASK (0xff << 8) +#define TSIZ_NTD_SHIFT 8 +#define TSIZ_SCHINFO_MASK (0xff << 0) +#define TSIZ_SCHINFO_SHIFT 0 +#define TSIZ_XFERSIZE_MASK (0x7ffff << 0) +#define TSIZ_XFERSIZE_SHIFT 0 +#define HCDMA(x) (0x514 + 0x20 * (x)) + +/*** DEVICE MODE REGISTERS ***/ +/* Device Global Registers */ +#define DCFG (0x800) +#define DCTL (0x804) +#define DSTS (0x808) +#define DIEPMSK (0x810) +#define DOEPMSK (0x814) +#define DAINT (0x818) +#define DAINTMSK (0x81C) +#define DTKNQR1 (0x820) +#define DTKNQR2 (0x824) +#define DVBUSDIS (0x828) +#define DVBUSPULSE (0x82C) +#define DTHRCTL (0x830) + +/* Device Logical IN Endpoint-Specific Registers */ +#define DIEPCTL(x) (0x900 + 0x20 * (x)) +#define DIEPINT(x) (0x908 + 0x20 * (x)) +#define DIEPTSIZ(x) (0x910 + 0x20 * (x)) +#define DIEPDMA(x) (0x914 + 0x20 * (x)) +#define DTXFSTS(x) (0x918 + 0x20 * (x)) + +/* Device Logical OUT Endpoint-Specific Registers */ +#define DOEPCTL(x) (0xB00 + 0x20 * (x)) +#define DOEPINT(x) (0xB08 + 0x20 * (x)) +#define DOEPTSIZ(x) (0xB10 + 0x20 * (x)) +#define DOEPDMA(x) (0xB14 + 0x20 * (x)) + +/* Power and Clock Gating Register */ +#define PCGCCTL (0xE00) + +#define EP0FIFO (0x1000) + +#define USB_ENDPOINT_XFER_CONTROL 0 +#define USB_ENDPOINT_XFER_ISOC 1 +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_XFER_INT 3 + +/** + * This union represents the bit fields in the DMA Descriptor + * status quadlet. Read the quadlet into the d32 member then + * set/clear the bits using the bit, b_iso_out and + * b_iso_in elements. + */ +typedef union dev_dma_desc_sts { + /** raw register data */ + unsigned int d32; + /** quadlet bits */ + struct { + /** Received number of bytes */ + unsigned bytes:16; + /** NAK bit - only for OUT EPs */ + unsigned nak:1; + unsigned reserved17_22:6; + /** Multiple Transfer - only for OUT EPs */ + unsigned mtrf:1; + /** Setup Packet received - only for OUT EPs */ + unsigned sr:1; + /** Interrupt On Complete */ + unsigned ioc:1; + /** Short Packet */ + unsigned sp:1; + /** Last */ + unsigned l:1; + /** Receive Status */ + unsigned sts:2; + /** Buffer Status */ + unsigned bs:2; + } b; +} dev_dma_desc_sts_t; + +/** + * DMA Descriptor structure + * + * DMA Descriptor structure contains two quadlets: + * Status quadlet and Data buffer pointer. + */ +typedef struct dwc_otg_dev_dma_desc { + /** DMA Descriptor status quadlet */ + dev_dma_desc_sts_t status; + /** DMA Descriptor data buffer pointer */ + UINT32 buf; +} dwc_otg_dev_dma_desc_t; + + + + + + + + + + + + + + +typedef struct _USB_OHCI_HC_DEV USB_OHCI_HC_DEV; + +struct _USB_OHCI_HC_DEV { + UINTN Signature; + EFI_USB_HC_PROTOCOL UsbHc; + EFI_USB2_HC_PROTOCOL Usb2Hc; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 OriginalPciAttributes; + +// HCCA_MEMORY_BLOCK *HccaMemoryBlock; + VOID *HccaMemoryBuf; + VOID *HccaMemoryMapping; + UINTN HccaMemoryPages; + +// ED_DESCRIPTOR *IntervalList[6][32]; +// INTERRUPT_CONTEXT_ENTRY *InterruptContextList; + VOID *MemPool; + + UINT32 ToggleFlag; + + EFI_EVENT HouseKeeperTimer; + // + // ExitBootServicesEvent is used to stop the OHC DMA operation + // after exit boot service. + // + EFI_EVENT ExitBootServiceEvent; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + UINT32 PortStatus; +}; + +#define USB_DW_HC_DEV_SIGNATURE SIGNATURE_32('d','u','s','b') +extern EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gOhciComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gOhciComponentName2; + +#define USB_OHCI_HC_DEV_FROM_THIS(a) CR(a, USB_OHCI_HC_DEV, UsbHc, USB_= DW_HC_DEV_SIGNATURE) +#define USB2_OHCI_HC_DEV_FROM_THIS(a) CR(a, USB_OHCI_HC_DEV, Usb2Hc, US= B_DW_HC_DEV_SIGNATURE) + + + + + +#endif //ifndef __DW_USB_DXE_H__ diff --git a/Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.inf b/Silicon/Synopsys/= Usb/DwUsbDxe/DwUsbDxe.inf new file mode 100644 index 000000000..e733e1172 --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.inf @@ -0,0 +1,60 @@ +#/** @file +# +# Copyright (c) 2015, Linaro Limited. All rights reserved. +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# Copyright (c) 2017, Jeremy Linton +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +# +# +#**/ + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D DwUsbDxe + FILE_GUID =3D 72d78ea6-4dee-11e3-8100-f3842a48d0a0 + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D DwUsbEntryPoint + +[Sources.common] + DwUsbDxe.c + ComponentName.c + +[LibraryClasses] + DebugLib + IoLib + MemoryAllocationLib + TimerLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UncachedMemoryAllocationLib + CacheMaintenanceLib + +[Guids] + gEfiEventExitBootServicesGuid ## consume + +[Protocols] + gEfiDriverBindingProtocolGuid + gUsbDeviceProtocolGuid + gEfiUsbHcProtocolGuid ## produce + gEfiPciIoProtocolGuid ## TO_START + + +[Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec + +[Pcd] + gDwUsbDxeTokenSpaceGuid.PcdDwUsbBaseAddress + gDwUsbDxeTokenSpaceGuid.PcdDwUsbSysCtrlBaseAddress diff --git a/Silicon/Synopsys/Usb/DwUsbHostDxe/ComponentName.c b/Silicon/Sy= nopsys/Usb/DwUsbHostDxe/ComponentName.c new file mode 100644 index 000000000..4357e091c --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbHostDxe/ComponentName.c @@ -0,0 +1,243 @@ +/** @file +UEFI Component Name and Name2 protocol for Designware USB driver. + +Copyright (c) 2013-2015 Intel Corporation. +Copyright (c) 2017 Jeremy Linton + +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 IMPLI= ED. + +**/ + + + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "ComponentName.h" +#include "DwUsbHostDxe.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gDwUsbComponent= Name =3D { + DwUsbComponentNameGetDriverName, + DwUsbComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gDwUsbComponent= Name2 =3D { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) DwUsbComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) DwUsbComponentNameGetControlle= rName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mDwUsbDriverNameTab= le[] =3D { + { "eng;en", L"Designware Usb Driver" }, + { NULL, NULL } +}; + + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form o= f a + Unicode string. If the driver specified by This has a user readable name= in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by + This and the language specified by Languag= e was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +DwUsbComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mDwUsbDriverNameTable, + DriverName, + (BOOLEAN)(This =3D=3D &gDwUsbComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +DwUsbComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status; + DWUSB_OTGHC_DEV *DwUsbDev; + EFI_USB2_HC_PROTOCOL *UsbHc; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle !=3D NULL) { + return EFI_UNSUPPORTED; + } + // + // Make sure this driver is currently managing ControllerHandle + // +/* Status =3D EfiTestManagedDevice ( + ControllerHandle, + gOhciDriverBinding.DriverBindingHandle, + &gEfiPciIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; +}*/ + // + // Get the device context + // + Status =3D gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsb2HcProtocolGuid, + (VOID **) &UsbHc, + gDwUsbDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DwUsbDev =3D DWHC_FROM_THIS(UsbHc); + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + DwUsbDev->ControllerNameTable, + ControllerName, + (BOOLEAN)(This =3D=3D &gDwUsbComponentName) + ); + +} diff --git a/Silicon/Synopsys/Usb/DwUsbHostDxe/ComponentName.h b/Silicon/Sy= nopsys/Usb/DwUsbHostDxe/ComponentName.h new file mode 100644 index 000000000..814a8501d --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbHostDxe/ComponentName.h @@ -0,0 +1,148 @@ +/** @file +UEFI Component Name and Name2 protocol for Designware USB driver. + +Copyright (c) 2013-2015 Intel Corporation. +Copyright (c) 2017 Jeremy Linton + +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 IMPLI= ED. + +**/ + +#ifndef _COMPONENT_NAME_H_ +#define _COMPONENT_NAME_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 o= f a + Unicode string. If the driver specified by This has a user readable name= in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver speci= fied + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code for= mat. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specifie= d by + This and the language specified by Languag= e was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +DwUsbComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the control= ler + that is being managed by a driver. + + This function retrieves the user readable name of the controller specifi= ed by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specif= ied by + Language, then a pointer to the controller name is returned in Controlle= rName, + and EFI_SUCCESS is returned. If the driver specified by This is not cur= rently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does = not + support the language specified by Language, then EFI_UNSUPPORTED is retu= rned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTO= COL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to = be + returned. + + @param ChildHandle[in] The handle of the child controller to retr= ieve + the name of. This is an optional paramete= r that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus d= rivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of= a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the calle= r is + requesting, and it must match one of the + languages specified in SupportedLanguages.= The + number of languages supported by a driver = is up + to the driver writer. Language is specifie= d in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle a= nd + ChildHandle in the language specified by + Language from the point of view of the dri= ver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable n= ame in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a va= lid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not curren= tly + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not supp= ort + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +DwUsbComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle O= PTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +#endif + diff --git a/Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.c b/Silicon/Syn= opsys/Usb/DwUsbHostDxe/DwUsbHostDxe.c new file mode 100644 index 000000000..28a3cde98 --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.c @@ -0,0 +1,2043 @@ +/** @file + + Copyright (c) 2015, Linaro Limited. All rights reserved. + Copyright (c) 2015, Hisilicon Limited. All rights reserved. + Copyright (c) 2017, Jeremy Linton + + 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 I= MPLIED. + +**/ + + +// Some notes about this driver: +// +// First as it stands all transfers are routed through the "nonperiodic" = queues +// including interrupt transfers. This means we emulate interrupt transfe= rs using +// the UEFI timer and a queue. All the fancy hardware scheduling is unuse= d. +// +// This also means that there is absolutely no prioritization, bandwidth = reservations +// or anything else that are generally required of interrupt/isochronous = transfers. +// +// We no round robin the channels, this in theory allows us to have multi= ple commands +// outstanding, but due to the fact that we are either using a timer and = mostly +// blocking thta timer during the command submission, its really unlikely= that we=20 +// have more than a single command outstanding. +// +// At the moment this is host only driver, and the phy config, which shou= ld be attached +// to the DW i2c channel likely isn't.=20 +// +// This driver defaults to High speed, but if we detect split transaction= problems with +// low/full speed devices then we reset the root port and everything atta= ched, and restart +// at a lower speed. This allows us to transparently support high/full/lo= w speed devices.=20 +// That said, it seems low speed devices don't really work worth a darn o= n this controller.=20 +// There are assorted knobs that can be tiwiddled to tweak the low speed = bitstream, but +// my USB analyzer is truly just a protocol analyzer and is unable to tel= l me how far out +// of spec the physical singaling is, and I'm currently to lazy to try an= analyze it=20 +// with my scope/logic analyzer. +// + +#include "DwUsbHostDxe.h" +#include "DwcHw.h" + +// Enabling this, disables attempting split transactions, and=20 +// sets the initial root port to full speed (rather than high) +// This option is less useful now that we detect full/low speed +// devices having split transaction problems and automatically=20 +// reset to full speed +#define DW_AT_FULLSPEED 0 + +// Forcing host mode may allow HS/FS/LS devices? Nah, doesn't=20 +// appear that way on the HiSi, but do it anyway for the time. +#define DW_FORCE_HOST 1=20 + +// This timer controls how frequently we wake up to service +// interrupt transfers (in milliseconds).=20 +#define DW_USB_POLL_TIMER 50 + +// timeout for interrupt transfers +#define DW_USB_POLL_INTERRUPT 100 //100 ms +// We delay ops for a few poll intervals following bulk transfers +// in a lame (non USB standard) way to avoid burning bandwidth +// on interrupt transfers if bulk/setup is active. This also +// avoids colliding interrupts with bulk transfers although this +// seems to work fine now. +#define POLL_DELAY 10 + + +VOID DwHcInit (IN DWUSB_OTGHC_DEV *DwHc); +VOID DwCoreInit (IN DWUSB_OTGHC_DEV *DwHc); + + +#define HI6220_PERI_BASE 0xF7030000 +#define PERI_SC_PERIPH_CLK0_EN 0x200 +#define PERI_SC_PERIPH_CLK0_DIS 0x204 +#define PERI_SC_PERIPH_CLK0_STAT 0x208 +/* this routine is the only really HiKey specific routine + in the module, replace it with appropriate calls elsewhere */ +VOID +ConfigureUsbPhy ( + VOID + ) +{ + UINT32 Data; + DEBUG ((EFI_D_VERBOSE, "ConfigureUsbPhy \n",__func__)); + /*Enable USB clock*/ + Data =3D MmioRead32 (HI6220_PERI_BASE + PERI_SC_PERIPH_CLK0_EN); + Data |=3D 0x10; + MmioWrite32 (HI6220_PERI_BASE + PERI_SC_PERIPH_CLK0_EN, 0x10); + + do { + Data =3D MmioRead32 (HI6220_PERI_BASE + PERI_SC_PERIPH_CLK0_STAT); + } while ((Data & 0x10) =3D=3D 0); + + /*Take USB IPs out of reset*/ + MmioWrite32 (0xF7030000 + 0x304, 0xF0); + + do { + Data =3D MmioRead32 (HI6220_PERI_BASE + 0x308); + Data &=3D 0xF0; + } while (Data); + + /*CTRL5*/ + Data =3D MmioRead32 (HI6220_PERI_BASE + 0x010); + Data &=3D ~0x20; + Data |=3D 0x318; + MmioWrite32 (HI6220_PERI_BASE + 0x010, Data); + + /*CTRL4*/ + /*Configure USB PHY*/ + Data =3D MmioRead32 (HI6220_PERI_BASE + 0x00C); + + /*make PHY out of low power mode*/ + Data &=3D ~0x40; + Data &=3D ~0x100; + Data |=3D 0xC00; + Data &=3D ~0x200000; + MmioWrite32 (HI6220_PERI_BASE + 0x00C, Data); + + MmioWrite32 (HI6220_PERI_BASE + 0x018, 0x70533483); //EYE_PATTERN + + MicroSecondDelay (5000); +} + +UINT32 +Wait4Bit ( + IN UINT32 Reg, + IN UINT32 Mask, + IN BOOLEAN Set + ) +{ + UINT32 Timeout =3D DW_USB_POLL_INTERRUPT; + UINT32 Value; + DEBUG ((EFI_D_VERBOSE, "Wait4Bit \n",__func__)); + + while (--Timeout) { + Value =3D MmioRead32 (Reg); + if (!Set) + Value =3D ~Value; + + if ((Value & Mask) =3D=3D Mask) { + DEBUG ((EFI_D_VERBOSE, "Wait4Bit val=3D%X return\n",Value)); + return 0; + } + + MicroSecondDelay (1); + } + +// DEBUG ((EFI_D_ERROR, "Wait4Bit: Timeout (Reg:0x%x, mask:0x%x, wait_s= et:%d, val:0x%X)\n", Reg, Mask, Set, Value)); + + return 1; +} + + +UINT32 +Wait4AnyBit ( + IN UINT32 Reg, + IN UINT32 Mask, + IN UINT32 MaskFail, + IN UINT32 Timeout // in milliseconds + ) +{ + UINT32 Value =3D MmioRead32 (Reg); + Timeout *=3D 1000; // we want this in microseconds + DEBUG ((EFI_D_VERBOSE, "Wait4AnyBit \n")); + + while (--Timeout) { + Value =3D MmioRead32 (Reg); + + if (Value & Mask) { + DEBUG ((EFI_D_VERBOSE, "Wait4AnyBit val=3D%X return\n",Value)); + return 0; + } + // fail early + if ((Timeout < DW_USB_POLL_INTERRUPT/4) & (Value & MaskFail)) { + DEBUG ((EFI_D_ERROR, "Wait4AnyBit val=3D%X early fail return\n",Value)); + return 0; + } + + MicroSecondDelay (1); + } + + DEBUG ((EFI_D_VERBOSE, "Wait4AnyBit: Timeout (Reg:0x%x, mask:0x%x, val= :0x%X)\n", Reg, Mask, Value)); + + return 1; +} + + +// The Num parameter corresponds to the FIFO being flushed +// 0000 Non periodic TX FIFO in host mode +// 0001 Periodic FIFO host mode +// xxx0 Device mode FIFO +// 10000 Flush all transmit FIFOs +VOID +DwFlushTxFifo ( + IN DWUSB_OTGHC_DEV *DwHc, + IN INT32 Num + ) +{ + UINT32 Status; + DEBUG ((EFI_D_VERBOSE, "DwFlushTxFifo \n",__func__)); + MmioWrite32 (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_TXFFLSH | (Num <<= DWC2_GRSTCTL_TXFNUM_OFFSET)); + + Status =3D Wait4Bit (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_TXFFLSH, = 0); + if (Status) + DEBUG ((EFI_D_ERROR, "DwFlushTxFifo: Timeout!\n")); + + MicroSecondDelay (1); +} + +VOID +DwFlushRxFifo ( + IN DWUSB_OTGHC_DEV *DwHc + ) +{ + UINT32 Status; + DEBUG ((EFI_D_VERBOSE, "DwFlushRxFifo \n",__func__)); + MmioWrite32 (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_RXFFLSH); + + Status =3D Wait4Bit (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_RXFFLSH, = 0); + if (Status) + DEBUG ((EFI_D_ERROR, "DwFlushRxFifo: Timeout!\n")); + + MicroSecondDelay (1); +} + +void DwUsbAttemptClear( + IN DWUSB_OTGHC_DEV *DwHc, + IN UINT32 Channel + ) +{ + + MmioWrite32 (DwHc->DwUsbBase + HCINT(Channel), 0x3FFF); =09 + // disable channel + MmioAndThenOr32 (DwHc->DwUsbBase + HCCHAR(Channel), + ~(DWC2_HCCHAR_CHEN | DWC2_HCCHAR_EPDIR), + DWC2_HCCHAR_CHDIS); + + DwFlushTxFifo (DwHc, 0x00); //flush non periodic queue + DwFlushRxFifo (DwHc); + + MicroSecondDelay (50000);=09 + + MmioWrite32 (DwHc->DwUsbBase + HCINT(Channel), 0x3FFF); =09 + + MmioAndThenOr32 (DwHc->DwUsbBase + HCCHAR(Channel), + ~(DWC2_HCCHAR_EPDIR|DWC2_HCCHAR_CHDIS), + DWC2_HCCHAR_CHEN|DWC2_HCCHAR_CHDIS); + Wait4Bit (DwHc->DwUsbBase + HCCHAR(Channel), DWC2_HCCHAR_CHEN, 0); +} + + +UINT32 +Wait4Chhltd ( + IN DWUSB_OTGHC_DEV *DwHc, + IN UINT32 Channel, + IN UINT32 *Sub, + IN UINT32 *Toggle, + IN BOOLEAN IgnoreAck, + IN BOOLEAN IgnoreComplete, + IN UINT32 Timeout + ) +{ + UINT32 HcintCompHltAck =3D DWC2_HCINT_XFERCOMP | DWC2_HCINT_CHHLTD; + INT32 Ret; + UINT32 Hcint, Hctsiz; + DEBUG ((EFI_D_VERBOSE, "Wait4Chhltd \n",__func__)); + + MicroSecondDelay (100); +// Ret =3D Wait4Bit (DwHc->DwUsbBase + HCINT(Channel), DWC2_HCINT_CHHLT= D, 1); //wait only for channel halt, cosider waiting for NAK/STALL too.... + +// Ret =3D Wait4AnyBit (DwHc->DwUsbBase + HCINT(Channel), DWC2_HCINT_CH= HLTD|DWC2_HCINT_XFERCOMP, DWC2_HCINT_NAK|DWC2_HCINT_STALL); //Ok really the= sequence should be wait for complete + // then halt the channel and wait for channel halt + Ret =3D Wait4AnyBit (DwHc->DwUsbBase + HCINT(Channel), DWC2_HCINT_CHHLTD,= DWC2_HCINT_NAK|DWC2_HCINT_STALL, Timeout); //for whatever reason just wait= ing for halt tends to work + + MicroSecondDelay (100); + Hcint =3D MmioRead32 (DwHc->DwUsbBase + HCINT(Channel)); + if (Hcint & DWC2_HCINT_STALL) { + DEBUG ((EFI_D_ERROR, "Wait4Chhltd: STALL Hcint=3D%X\n", Hcint)); + DwUsbAttemptClear(DwHc, Channel); + return EFI_USB_ERR_STALL; + } + if (Hcint & DWC2_HCINT_BBLERR) { + DEBUG ((EFI_D_ERROR, "Wait4Chhltd: BABBLE Hcint=3D%X\n", Hcint)); + return EFI_USB_ERR_BABBLE; + } =20 + if (Hcint & DWC2_HCINT_FRMOVRUN) { + DEBUG ((EFI_D_VERBOSE, "Wait4Chhltd: Overrun Hcint=3D%X\n", Hcint)= ); + return EFI_USB_ERR_SYSTEM+1; + } + + if (Hcint & DWC2_HCINT_XACTERR) { + DEBUG ((EFI_D_ERROR, "Wait4Chhltd: CRC/bitstuff/etc error Hcint=3D= %X\n", Hcint)); + return EFI_USB_ERR_CRC; + } + + if (Hcint & DWC2_HCINT_NAK) { + //NAKs are part of the normal interrupt protocol + DEBUG ((EFI_D_VERBOSE, "Wait4Chhltd: NAK Hcint=3D%X\n", Hcint));=20 + return EFI_USB_ERR_NAK; + } + + if (Hcint & DWC2_HCINT_DATATGLERR) { + DEBUG ((EFI_D_ERROR, "Wait4Chhltd: DATA toggle Hcint=3D%X\n", Hcin= t)); + return EFI_USB_ERR_SYSTEM; //what is the correct return?=20 + } + + // Moved this down here so that NAK & other error conditions are=20 + // handled before timeout + if (Ret) { + DEBUG ((EFI_D_VERBOSE, "Wait4Chhltd ret\n")); + DwUsbAttemptClear(DwHc, Channel); + return EFI_USB_ERR_TIMEOUT; + } + + // A happy transfer is halted/complete/acked + // an ignore ack transaction is just complete/halted + if (IgnoreAck) { + Hcint &=3D ~DWC2_HCINT_ACK; + } + else { + HcintCompHltAck |=3D DWC2_HCINT_ACK; + } + if (IgnoreComplete) { + Hcint |=3D DWC2_HCINT_XFERCOMP; + } + + if (Hcint !=3D HcintCompHltAck) { + DEBUG ((EFI_D_ERROR, "Wait4Chhltd: HCINT Error 0x%x\n", Hcint)); + return EFI_USB_ERR_STALL; //JL take this out to unstick device? + } + + Hctsiz =3D MmioRead32 (DwHc->DwUsbBase + HCTSIZ(Channel)); + *Sub =3D (Hctsiz & DWC2_HCTSIZ_XFERSIZE_MASK) >> DWC2_HCTSIZ_XFERSIZE_= OFFSET; + *Toggle =3D (Hctsiz & DWC2_HCTSIZ_PID_MASK) >> DWC2_HCTSIZ_PID_OFFSET; + + return EFI_USB_NOERROR; +} + +VOID +DwOtgHcInit ( + IN DWUSB_OTGHC_DEV *DwHc, + IN UINT8 Channel, + IN UINT8 DevAddr, + IN UINT8 Endpoint, + IN UINT8 EpDir, + IN UINT8 EpType, + IN UINT16 MaxPacket, + IN UINT8 DeviceSpeed, + IN UINT8 TtPort, + IN UINT8 TtHub, + IN UINT8 DoComplete + ) +{ + UINT32 Split =3D 0; + UINT32 Hcchar =3D (DevAddr << DWC2_HCCHAR_DEVADDR_OFFSET) | + (Endpoint << DWC2_HCCHAR_EPNUM_OFFSET) | + (EpDir << DWC2_HCCHAR_EPDIR_OFFSET) | + (EpType << DWC2_HCCHAR_EPTYPE_OFFSET) | + (MaxPacket << DWC2_HCCHAR_MPS_OFFSET); + + if ((DeviceSpeed !=3D EFI_USB_SPEED_HIGH) && (!DwHc->AtFullSpeed)) + { + DEBUG ((EFI_D_ERROR, "Split Message to %d speed device (%d,%d) \n", Dev= iceSpeed, TtPort, TtHub)); + Split =3D TtPort | (TtHub << DWC2_HCSPLT_HUBADDR_OFFSET); + Split |=3D DWC2_HCSPLT_XACTPOS_ALL << DWC2_HCSPLT_XACTPOS_OFFSET; //do a= ll packets? Or just the data payload? +// Split |=3D DWC2_HCSPLT_XACTPOS_BEGIN << DWC2_HCSPLT_XACTPOS_OFFSET; + Split |=3D DoComplete?DWC2_HCSPLT_COMPSPLT:0; + //Split |=3D DWC2_HCSPLT_COMPSPLT; //do a complete split transaction? (d= ocs aren't 100% clear on what this means, although maybe its because i'm in= DMA mode (hint that splits may not work with DMA) + Split |=3D DWC2_HCSPLT_SPLTENA; + // Do we need to set lowspeed? I'm guessing this is only when the root p= ort is full/low + // because the "speed" of a split transaction is still high to the TT.. + Hcchar |=3D DWC2_HCCHAR_LSPDDEV; + }=20 + else if (DeviceSpeed =3D=3D EFI_USB_SPEED_LOW) + { + Hcchar |=3D DWC2_HCCHAR_LSPDDEV; + } + + DEBUG ((EFI_D_VERBOSE, "DwOtgHcInit \n",__func__)); + + MmioWrite32 (DwHc->DwUsbBase + HCINT(Channel), 0x3FFF); + + MmioWrite32 (DwHc->DwUsbBase + HCCHAR(Channel), Hcchar); + + MmioWrite32 (DwHc->DwUsbBase + HCSPLT(Channel), Split);=20 +} + +VOID +DwCoreReset ( + IN DWUSB_OTGHC_DEV *DwHc + ) +{ + UINT32 Status; + DEBUG ((EFI_D_VERBOSE, "DwCoreReset \n",__func__)); + + Status =3D Wait4Bit (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_AHBIDLE, = 1); + if (Status) + DEBUG ((EFI_D_ERROR, "DwCoreReset: Timeout!\n")); + + MmioWrite32 (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_CSFTRST); + + Status =3D Wait4Bit (DwHc->DwUsbBase + GRSTCTL, DWC2_GRSTCTL_CSFTRST, = 0); + if (Status) + DEBUG ((EFI_D_ERROR, "DwCoreReset: Timeout!\n")); + + MicroSecondDelay (100000); +} + +EFI_STATUS +DwHcTransfer ( + IN DWUSB_OTGHC_DEV *DwHc, + IN UINT8 DeviceAddress, + IN UINTN MaximumPacketLength, + IN OUT UINT32 *Pid, + IN UINT32 TransferDirection, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINT32 EpAddress, + IN UINT32 EpType, + OUT UINT32 *TransferResult, + IN BOOLEAN IgnoreAck, + IN BOOLEAN DoPing, + IN UINT8 DeviceSpeed, + IN UINT8 TtPort, + IN UINT8 TtHub, + IN UINT8 IgnoreComplete, + IN UINT32 Timeout + ) +{ + UINT32 TxferLen; + UINTN BufferLen; + UINT32 Done =3D 0; + UINT32 NumPackets; + UINT32 Sub; + UINT32 StopTransfer =3D 0; + EFI_STATUS Status =3D EFI_SUCCESS; + UINT32 SplitDone =3D 0; + EFI_PHYSICAL_ADDRESS BusPhysAddr; + VOID *Mapping =3D NULL; + // picking a channel based on EP works in this driver but doesn't seem to= afford andy + // advantages (at the moment). +// UINT32 Channel =3D (EpAddress & 0x7F) % DWC2_M= AX_CHANNELS; + EFI_TPL OriginalTPL; =09 +// UINT32 Channel =3D DWC2_HC_CHANNEL; //just use= channel 0 for everything +// UINT32 Channel =3D 0; + + static UINT32 StaticChannel =3D 0; + UINT32 Channel =3D (StaticChannel++) % DWC2_MAX_= CHANNELS; + UINT32 ChannelRetries =3D DWC2_MAX_CHANNELS; + + OriginalTPL =3D gBS->RaiseTPL(TPL_HIGH_LEVEL); =20 + for (ChannelRetries =3D 0 ; ChannelRetries < DWC2_MAX_CHANNELS; ChannelRe= tries++) + { + if (DwHc->ActiveChannel[Channel]) + { + Channel++; + DEBUG ((EFI_D_ERROR, "DwHcTransfer: Channel Collision\n")); + } + else + { + DwHc->ActiveChannel[Channel] =3D TRUE; + break; + } + } + gBS->RestoreTPL (OriginalTPL); + + if (ChannelRetries =3D=3D DWC2_MAX_CHANNELS) + { + DEBUG ((EFI_D_ERROR, "DwHcTransfer: Out of channels\n")); + } + DEBUG ((EFI_D_VERBOSE, "DwHcTransfer channel=3D%d\n",Channel)); + + + OriginalTPL =3D gBS->RaiseTPL(TPL_NOTIFY); + + do { + DwOtgHcInit (DwHc, Channel, DeviceAddress, EpAddress, TransferDire= ction, EpType, MaximumPacketLength, DeviceSpeed, TtPort, TtHub, SplitDone); + + TxferLen =3D *DataLength - Done; + if (TxferLen > DWC2_MAX_TRANSFER_SIZE) + TxferLen =3D DWC2_MAX_TRANSFER_SIZE - MaximumPacketLength + 1; + if (TxferLen > DWC2_DATA_BUF_SIZE) + TxferLen =3D DWC2_DATA_BUF_SIZE - MaximumPacketLength + 1; + + if (TxferLen > 0) { + NumPackets =3D (TxferLen + MaximumPacketLength - 1) / MaximumP= acketLength; + if (NumPackets > DWC2_MAX_PACKET_COUNT) { + NumPackets =3D DWC2_MAX_PACKET_COUNT; + TxferLen =3D NumPackets * MaximumPacketLength; + } + } else { + NumPackets =3D 1; + } + + if (TransferDirection) + TxferLen =3D NumPackets * MaximumPacketLength; + + MmioWrite32 (DwHc->DwUsbBase + HCTSIZ(Channel), (TxferLen << DWC2_= HCTSIZ_XFERSIZE_OFFSET) | + (NumPackets << DWC2_HCTSIZ_PKTCNT_OFFSET) | (DoPing <= < DWC2_HCTSIZ_DOPNG_OFFSET) | + (*Pid << DWC2_HCTSIZ_PID_OFFSET)); + + DEBUG ((EFI_D_VERBOSE, "Usb: dma (%d) size %d %d\n",TransferDirection, *= DataLength, TxferLen)); + + if (TransferDirection) // direction=3D1 IN from USB + { + if (*DataLength < TxferLen) + { + BufferLen =3D *DataLength; + } + else + { + BufferLen =3D TxferLen; + } + Status =3D DwHc->PciIo->Map (DwHc->PciIo, EfiPciIoOperationBusMasterWri= te , Data+Done , &BufferLen, &BusPhysAddr, &Mapping); + } + else=20 + { + BufferLen =3D TxferLen; + Status =3D DwHc->PciIo->Map (DwHc->PciIo, EfiPciIoOperationBusMasterRea= d , Data+Done , &BufferLen, &BusPhysAddr, &Mapping); + } + + // something is horribly wrong with the way i'm binding the PciIo if thi= s stabilizes=20 + // the transfers (and it removes nearly all the remaining stalls) + asm("dsb sy"); + asm("isb sy"); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Usb: Map DMA failed\n")); + } + + MmioWrite32 (DwHc->DwUsbBase + HCDMA(Channel), (UINTN)BusPhysAddr); + + MmioAndThenOr32 (DwHc->DwUsbBase + HCCHAR(Channel), ~(DWC2_HCCHAR_= MULTICNT_MASK | + DWC2_HCCHAR_CHEN | + DWC2_HCCHAR_CHDIS), + ((1 << DWC2_HCCHAR_MULTICNT_OFFSET) | + DWC2_HCCHAR_CHEN)); + +// ArmDataSynchronizationBarrier(); + + *TransferResult =3D Wait4Chhltd (DwHc, Channel, &Sub, Pid, IgnoreA= ck, IgnoreComplete, Timeout); + if ((DeviceSpeed !=3D EFI_USB_SPEED_HIGH) && (!SplitDone) && (!DwHc->AtF= ullSpeed)) + { + SplitDone++; + MmioWrite32 (DwHc->DwUsbBase + HCINT(Channel), 0x3FFF); + MmioAndThenOr32 (DwHc->DwUsbBase + HCCHAR(Channel), ~(DWC2_HCCHAR_MULTI= CNT_MASK | DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS), + ((1 << DWC2_HCCHAR_MULTICNT_OFFSET) | DWC2_HCCHAR_CHEN | DWC2_HCSP= LT_COMPSPLT)); + *TransferResult =3D Wait4Chhltd (DwHc, Channel, &Sub, Pid, IgnoreAck, I= gnoreComplete, Timeout); +// continue; + } + + DwHc->PciIo->Flush(DwHc->PciIo); + + if (Mapping) + { + DwHc->PciIo->Unmap (DwHc->PciIo, Mapping); + Mapping =3D NULL; + } + + if (*TransferResult) { + DEBUG ((EFI_D_VERBOSE, "DwHcTransfer: failed\n")); + Status =3D EFI_DEVICE_ERROR; + break; + } + + if (TransferDirection) { + TxferLen -=3D Sub; + if (Sub) + StopTransfer =3D 1; + } + + + Done +=3D TxferLen; + } while (Done < *DataLength && !StopTransfer); + + MmioWrite32 (DwHc->DwUsbBase + HCINTMSK(Channel), 0); + MmioWrite32 (DwHc->DwUsbBase + HCINT(Channel), 0xFFFFFFFF); + + *DataLength =3D Done; + + gBS->RestoreTPL (OriginalTPL); + + OriginalTPL =3D gBS->RaiseTPL(TPL_HIGH_LEVEL); =20 + DwHc->ActiveChannel[Channel] =3D FALSE; + gBS->RestoreTPL (OriginalTPL); + + return Status; +} + +/** + EFI_USB2_HC_PROTOCOL APIs +**/ + +EFI_STATUS +EFIAPI +DwHcGetCapability ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ) +{ + DWUSB_OTGHC_DEV *DwHc; + DEBUG ((EFI_D_VERBOSE, "DwHcGetCapability \n",__func__)); + + DwHc =3D DWHC_FROM_THIS (This); + + if ((MaxSpeed =3D=3D NULL) || (PortNumber =3D=3D NULL) || (Is64BitCapa= ble =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (DwHc->AtFullSpeed) + { + *MaxSpeed =3D EFI_USB_SPEED_FULL; + } + else + { + *MaxSpeed =3D EFI_USB_SPEED_HIGH; + } + *PortNumber =3D 1; + *Is64BitCapable =3D 1; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DwHcReset ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT16 Attributes + ) +{ + DWUSB_OTGHC_DEV *DwHc; + DEBUG ((EFI_D_ERROR, "Designware HostController Reset\n")); + + DwHc =3D DWHC_FROM_THIS (This); + + ConfigureUsbPhy (); + DwCoreInit(DwHc); + DwHcInit(DwHc); + + MmioAndThenOr32 (DwHc->DwUsbBase + HPRT0, + ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG), + DWC2_HPRT0_PRTRST); + + MicroSecondDelay (50000); + + MmioAnd32 (DwHc->DwUsbBase + HPRT0, ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_P= RTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT= 0_PRTOVRCURRCHNG | + DWC2_HPRT0_PRTRST)); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DwHcGetState ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ) +{ + DWUSB_OTGHC_DEV *DwHc; + + DEBUG ((EFI_D_VERBOSE, "GetState \n",__func__)); + + DwHc =3D DWHC_FROM_THIS (This); + + *State =3D DwHc->DwHcState; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DwHcSetState ( + IN EFI_USB2_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ) +{ + DWUSB_OTGHC_DEV *DwHc; + DEBUG ((EFI_D_VERBOSE, "DwHcSetState \n",__func__)); + + DwHc =3D DWHC_FROM_THIS (This); + + DwHc->DwHcState =3D State; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DwHcGetRootHubPortStatus ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +{ + DWUSB_OTGHC_DEV *DwHc; + UINT32 Hprt0; + static int first =3D 1; +// DEBUG ((EFI_D_ERROR, "%s \n",L __func__)); +// DEBUG ((EFI_D_ERROR, "GetPortStatus \n")); + + if (first) + { + first =3D 0 ; + DEBUG ((EFI_D_ERROR, "DwHcReset first \n")); + DwHcReset(This,0); + } + + if (PortNumber > DWC2_HC_CHANNEL) + return EFI_INVALID_PARAMETER; + + if (PortStatus =3D=3D NULL) + return EFI_INVALID_PARAMETER; + + DwHc =3D DWHC_FROM_THIS (This); + + PortStatus->PortStatus =3D 0; + PortStatus->PortChangeStatus =3D 0; + + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + + if (Hprt0 & DWC2_HPRT0_PRTCONNSTS) { + PortStatus->PortStatus |=3D USB_PORT_STAT_CONNECTION; + } + + if (Hprt0 & DWC2_HPRT0_PRTENA) { + PortStatus->PortStatus |=3D USB_PORT_STAT_ENABLE; + } + + if (Hprt0 & DWC2_HPRT0_PRTSUSP) { + PortStatus->PortStatus |=3D USB_PORT_STAT_SUSPEND; + } + + if (Hprt0 & DWC2_HPRT0_PRTOVRCURRACT) { + PortStatus->PortStatus |=3D USB_PORT_STAT_OVERCURRENT; + } + + if (Hprt0 & DWC2_HPRT0_PRTRST) { + PortStatus->PortStatus |=3D USB_PORT_STAT_RESET; + } + + if (Hprt0 & DWC2_HPRT0_PRTPWR) { + PortStatus->PortStatus |=3D USB_PORT_STAT_POWER; + } + + if (!DwHc->AtFullSpeed) + { + PortStatus->PortStatus |=3D USB_PORT_STAT_HIGH_SPEED; + } + + if (Hprt0 & DWC2_HPRT0_PRTENCHNG) { +// PortStatus->PortChangeStatus |=3D USB_PORT_STAT_C_ENABLE; + } + + if (Hprt0 & DWC2_HPRT0_PRTCONNDET) { + PortStatus->PortChangeStatus |=3D USB_PORT_STAT_C_CONNECTION; + } + + if (Hprt0 & DWC2_HPRT0_PRTOVRCURRCHNG) { + PortStatus->PortChangeStatus |=3D USB_PORT_STAT_C_OVERCURRENT; + } + +// DEBUG ((EFI_D_ERROR, "GetPortStatus %X %X\n",PortStatus->PortStatus,Po= rtStatus->PortChangeStatus)); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DwHcSetRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + DWUSB_OTGHC_DEV *DwHc; + UINT32 Hprt0; + EFI_STATUS Status =3D EFI_SUCCESS; + + DEBUG ((EFI_D_ERROR, "DwHcSetRootHubPortFeature \n")); + + if (PortNumber > DWC2_HC_CHANNEL) { + Status =3D EFI_INVALID_PARAMETER; + goto End; + } + + DwHc =3D DWHC_FROM_THIS (This); + + switch (PortFeature) { + case EfiUsbPortEnable: + break; + case EfiUsbPortSuspend: + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + Hprt0 &=3D ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); + Hprt0 |=3D DWC2_HPRT0_PRTSUSP; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + break; + case EfiUsbPortReset: + MmioAndThenOr32 (DwHc->DwUsbBase + HPRT0, + ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCUR= RCHNG), + DWC2_HPRT0_PRTRST); + MicroSecondDelay (50000); + MmioAnd32 (DwHc->DwUsbBase + HPRT0, ~DWC2_HPRT0_PRTRST); + break; + case EfiUsbPortPower: + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + Hprt0 &=3D ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); + Hprt0 |=3D DWC2_HPRT0_PRTPWR; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + break; + case EfiUsbPortOwner: + break; + default: + Status =3D EFI_INVALID_PARAMETER; + break; + } + + End: + return Status; +} + +EFI_STATUS +EFIAPI +DwHcClearRootHubPortFeature ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +{ + DWUSB_OTGHC_DEV *DwHc; + UINT32 Hprt0; + EFI_STATUS Status =3D EFI_SUCCESS; + + DEBUG ((EFI_D_ERROR, "DwHcClearRootHubPortFeature \n")); + + if (PortNumber > DWC2_HC_CHANNEL) { + Status =3D EFI_INVALID_PARAMETER; + goto End; + } + + DwHc =3D DWHC_FROM_THIS (This); + + switch (PortFeature) { + case EfiUsbPortEnable: + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + Hprt0 &=3D ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); + Hprt0 |=3D DWC2_HPRT0_PRTENA; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + break; + case EfiUsbPortReset: + MmioAndThenOr32 (DwHc->DwUsbBase + HPRT0, + ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCUR= RCHNG), + DWC2_HPRT0_PRTRST); + MicroSecondDelay (50000); + MmioAnd32 (DwHc->DwUsbBase + HPRT0, ~DWC2_HPRT0_PRTRST); + break; + case EfiUsbPortSuspend: + MmioWrite32 (DwHc->DwUsbBase + PCGCCTL, 0); + MicroSecondDelay (40000); + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + Hprt0 &=3D ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); + Hprt0 |=3D DWC2_HPRT0_PRTRES; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + Hprt0 &=3D ~DWC2_HPRT0_PRTSUSP; + MicroSecondDelay (150000); + Hprt0 &=3D ~DWC2_HPRT0_PRTRES; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + break; + case EfiUsbPortPower: + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + Hprt0 &=3D ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); + Hprt0 &=3D ~DWC2_HPRT0_PRTPWR; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + break; + case EfiUsbPortOwner: + break; + case EfiUsbPortConnectChange: + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + Hprt0 &=3D ~DWC2_HPRT0_PRTCONNDET; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + break; + case EfiUsbPortResetChange: + break; + case EfiUsbPortEnableChange: + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + Hprt0 &=3D ~DWC2_HPRT0_PRTENCHNG; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + break; + case EfiUsbPortSuspendChange: + break; + case EfiUsbPortOverCurrentChange: + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + Hprt0 &=3D ~DWC2_HPRT0_PRTOVRCURRCHNG; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + break; + default: + Status =3D EFI_INVALID_PARAMETER; + break; + } + + End: + return Status; +} + +void DumpRequest(EFI_USB_DEVICE_REQUEST *Request) +{ + if (Request->RequestType & 0x80) { + DEBUG ((EFI_D_VERBOSE, "USB: RequestType %X -> Host\n",Request->RequestT= ype)); + } + else { + DEBUG ((EFI_D_VERBOSE, "USB: RequestType %X -> Device\n",Request->Reques= tType)); + } + if (Request->RequestType & 0x60) { + DEBUG ((EFI_D_VERBOSE, "USB: -> CLS/VEND\n")); + } + else { + DEBUG ((EFI_D_VERBOSE, "USB: -> STD\n")); + } + switch (Request->RequestType & 0x03) { + case USB_TARGET_DEVICE: + DEBUG ((EFI_D_VERBOSE, "USB: -> DEVICE\n")); + break; + case USB_TARGET_INTERFACE: + DEBUG ((EFI_D_VERBOSE, "USB: -> ITERFACE\n")); + break; + case USB_TARGET_ENDPOINT: + DEBUG ((EFI_D_VERBOSE, "USB: -> ENDPOINT\n")); + break; + case USB_TARGET_OTHER: + DEBUG ((EFI_D_VERBOSE, "USB: -> OTHER\n")); + break; + } + DEBUG ((EFI_D_VERBOSE, "USB: RequestType 0x%X\n",Request->RequestType)); + switch (Request->Request) { + case USB_DEV_GET_STATUS: + DEBUG ((EFI_D_VERBOSE, "USB: GET STATUS\n")); + break; + case USB_DEV_CLEAR_FEATURE: + DEBUG ((EFI_D_VERBOSE, "USB: CLEAR FEATURE\n")); + break; + case USB_DEV_SET_FEATURE: + DEBUG ((EFI_D_VERBOSE, "USB: SET FEATURE\n")); + break; + case USB_DEV_SET_ADDRESS: + DEBUG ((EFI_D_VERBOSE, "USB: SET ADDRESS\n")); + break; + case USB_DEV_GET_DESCRIPTOR: + DEBUG ((EFI_D_VERBOSE, "USB: GET DESCRIPTOR\n")); + break; + case USB_DEV_SET_DESCRIPTOR: + DEBUG ((EFI_D_VERBOSE, "USB: SET DESCRIPTOR\n")); + break; + default: + break; + } + DEBUG ((EFI_D_VERBOSE, "USB: Request %d\n",Request->Request)); + DEBUG ((EFI_D_VERBOSE, "USB: Value 0x%X\n",Request->Value)); + DEBUG ((EFI_D_VERBOSE, "USB: Index 0x%X\n",Request->Index)); + DEBUG ((EFI_D_VERBOSE, "USB: Length %d\n",Request->Length)); +} + + +EFI_STATUS +EFIAPI +DwHcControlTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + DWUSB_OTGHC_DEV *DwHc; + EFI_STATUS Status; + UINT32 Pid; + UINTN Length; + EFI_USB_DATA_DIRECTION StatusDirection; + UINT32 Direction; + UINT8 *StatusBuffer; + EFI_TPL OriginalTPL; =09 + + DEBUG ((EFI_D_VERBOSE, "DwHcControlTranfer \n")); + DumpRequest(Request); + + if ((Request =3D=3D NULL) || (TransferResult =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((TransferDirection !=3D EfiUsbDataIn) && + (TransferDirection !=3D EfiUsbDataOut) && + (TransferDirection !=3D EfiUsbNoData)) { + return EFI_INVALID_PARAMETER; + } + + if ((TransferDirection =3D=3D EfiUsbNoData) && + ((Data !=3D NULL) || (*DataLength !=3D 0))) { + return EFI_INVALID_PARAMETER; + } + + if ((TransferDirection !=3D EfiUsbNoData) && + ((Data =3D=3D NULL) || (*DataLength =3D=3D 0))) { + return EFI_INVALID_PARAMETER; + } + + if ((MaximumPacketLength !=3D 8) && (MaximumPacketLength !=3D 16) && + (MaximumPacketLength !=3D 32) && (MaximumPacketLength !=3D 64)) { + return EFI_INVALID_PARAMETER; + } + + if ((DeviceSpeed =3D=3D EFI_USB_SPEED_LOW) && (MaximumPacketLength != =3D 8)) { + return EFI_INVALID_PARAMETER; + } + + DwHc =3D DWHC_FROM_THIS(This); + + OriginalTPL =3D gBS->RaiseTPL(TPL_HIGH_LEVEL); + DwHc->BulkActive=3DPOLL_DELAY; + gBS->RestoreTPL (OriginalTPL); + + *TransferResult =3D EFI_USB_ERR_SYSTEM; + Status =3D EFI_DEVICE_ERROR; + + Pid =3D DWC2_HC_PID_SETUP; + Length =3D 8; + Status =3D DwHcTransfer (DwHc, DeviceAddress, MaximumPacketLength, &Pi= d, 0, Request, &Length, + 0, DWC2_HCCHAR_EPTYPE_CONTROL, TransferResult, = 1, 0, DeviceSpeed,=20 + Translator->TranslatorPortNumber, Translator->TranslatorHubAddres= s, 0, TimeOut); + + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "DwHcControlTransfer: Setup Stage Error\n")); + if ((DeviceSpeed !=3D EFI_USB_SPEED_HIGH) && (DwHc->AtFullSpeed =3D=3D 0= )) + { + DEBUG ((EFI_D_ERROR, "DwHcControlTransfer: Split transaction failed, re= ducing bus speed\n")); + DwHc->AtFullSpeed =3D 1; + DwHcReset(This, 0); + } + Status =3D EFI_USB_ERR_SYSTEM; + goto EXIT; + } + + if (Data) { + Pid =3D DWC2_HC_PID_DATA1; + + if (TransferDirection =3D=3D EfiUsbDataIn) + Direction =3D 1; + else + Direction =3D 0; + + Status =3D DwHcTransfer (DwHc, DeviceAddress, MaximumPacketLength,= &Pid, Direction, + Data, DataLength, 0, DWC2_HCCHAR_EPTYPE_CON= TROL, TransferResult, 0, 0, DeviceSpeed,=20 + Translator->TranslatorPortNumber, Translator->TranslatorHubAddre= ss, 0, TimeOut); + + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "DwHcControlTransfer: Data Stage Error\n"= )); + goto EXIT; + } + } + + if ((TransferDirection =3D=3D EfiUsbDataOut) || (TransferDirection =3D= =3D EfiUsbNoData)) + StatusDirection =3D 1; + else + StatusDirection =3D 0; + + Pid =3D DWC2_HC_PID_DATA1; + Length =3D 0; + + StatusBuffer =3D UncachedAllocatePages (EFI_SIZE_TO_PAGES (DWC2_STATUS= _BUF_SIZE)); + if (StatusBuffer =3D=3D NULL) { + DEBUG ((EFI_D_ERROR, "CreateDwUsbHc: No page availablefor StatusBu= ffer\n")); + goto EXIT; + } + + Status =3D DwHcTransfer (DwHc, DeviceAddress, MaximumPacketLength, &Pi= d, StatusDirection, StatusBuffer, + &Length, 0, DWC2_HCCHAR_EPTYPE_CONTROL, Transfe= rResult, 0, 0, DeviceSpeed, + Translator->TranslatorPortNumber, Translator->TranslatorHubAddres= s, 0, TimeOut); + + UncachedFreePages (StatusBuffer, EFI_SIZE_TO_PAGES (DWC2_STATUS_BUF_SI= ZE)); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "DwHcControlTransfer: Status Stage Error\n")); + } + + EXIT: + return Status; +} + +EFI_STATUS +EFIAPI +DwHcBulkTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_= NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + DWUSB_OTGHC_DEV *DwHc; + EFI_STATUS Status; + UINT8 TransferDirection; + UINT8 EpAddress; + UINT32 Pid; + UINT8 Ping; + EFI_TPL OriginalTPL; =09 + + DEBUG ((EFI_D_VERBOSE, "DwHcBulkTransfer DEV=3D%X EP=3D%X LEN=3D%X \n"= ,DeviceAddress,EndPointAddress,*DataLength)); + if ((Data =3D=3D NULL) || (Data[0] =3D=3D NULL) || + (DataLength =3D=3D NULL) || (*DataLength =3D=3D 0) || + (TransferResult =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((*DataToggle !=3D 0) && (*DataToggle !=3D 1)) + return EFI_INVALID_PARAMETER; + + if ((DeviceSpeed =3D=3D EFI_USB_SPEED_LOW) || (DeviceSpeed =3D=3D EFI_= USB_SPEED_SUPER)) + return EFI_INVALID_PARAMETER; + + if (((DeviceSpeed =3D=3D EFI_USB_SPEED_FULL) && (MaximumPacketLength >= 64)) || + ((DeviceSpeed =3D=3D EFI_USB_SPEED_HIGH) && (MaximumPacketLength >= 512))) + return EFI_INVALID_PARAMETER; + + DwHc =3D DWHC_FROM_THIS (This); + + *TransferResult =3D EFI_USB_ERR_SYSTEM; + Status =3D EFI_DEVICE_ERROR; + TransferDirection =3D (EndPointAddress >> 7) & 0x01; //IN =3D 1, OUT = =3D 0 + EpAddress =3D EndPointAddress & 0x0F; + Pid =3D (*DataToggle << 1); + Ping =3D 0; +// Ping =3D TransferDirection; //for write do ping first + + OriginalTPL =3D gBS->RaiseTPL(TPL_HIGH_LEVEL); + DwHc->BulkActive=3DPOLL_DELAY; + gBS->RestoreTPL (OriginalTPL); + + Status =3D DwHcTransfer (DwHc, DeviceAddress, MaximumPacketLength, &Pi= d, TransferDirection, Data[0], DataLength, + EpAddress, DWC2_HCCHAR_EPTYPE_BULK, TransferRes= ult, 1, Ping, DeviceSpeed, + Translator->TranslatorPortNumber, Translator->TranslatorHubAddres= s, 0, TimeOut); + + *DataToggle =3D (Pid >> 1); + +// MicroSecondDelay (5000); +// DwHc->BulkActive=3DPOLL_DELAY; + + return Status; +} + +EFI_STATUS +EFIAPI +DwHcAsyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval, + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, + IN VOID *Context OPTIONAL + ) +{ + DWUSB_OTGHC_DEV *DwHc; + EFI_STATUS Status; + EFI_TPL OriginalTPL; =09 + DWUSB_INTERRUPT_QUEUE *CompletionEntry; + DEBUG ((EFI_D_VERBOSE, "DwHcAsyncInterruptTransfer Addr=3D%d, EP=3D%d = len=3D%d new=3D%d Interval=3D%d(%d)\n",DeviceAddress, EndPointAddress, Data= Length, IsNewTransfer, PollingInterval, PollingInterval/DW_USB_POLL_TIMER)); + + if (!(EndPointAddress & USB_ENDPOINT_DIR_IN)) { + DEBUG ((EFI_D_ERROR, "DwHcAsyncInterruptTransfer: endpoint directi= on not right\n")); + return EFI_INVALID_PARAMETER; + } + + DwHc =3D DWHC_FROM_THIS (This); + + if (IsNewTransfer) { + if (DataLength =3D=3D 0) { + DEBUG ((EFI_D_ERROR, "DwHcAsyncInterruptTransfer: invalid len\= n")); + return EFI_INVALID_PARAMETER; + } + + if ((*DataToggle !=3D 1) && (*DataToggle !=3D 0)) { + DEBUG ((EFI_D_ERROR, "DwHcAsyncInterruptTransfer: invalid data= toggle\n")); + return EFI_INVALID_PARAMETER; + } + + if ((PollingInterval > 255) || (PollingInterval < 1)) { + DEBUG ((EFI_D_ERROR, "DwHcAsyncInterruptTransfer: Invalid poll= ing interval\n")); + return EFI_INVALID_PARAMETER; + } + } + else { + // The async nature of this callback is bonkers with + // relation to how it should work. So we do all the=20 + // "scheduled" processing in the foreground and then + // just queue the results.. + OriginalTPL =3D gBS->RaiseTPL(TPL_HIGH_LEVEL); + // Which means we want to cancel any outstanding items here.. + CompletionEntry =3D DwHc->InterruptQueue; + while (CompletionEntry) { + if ((CompletionEntry->DeviceAddress =3D=3D DeviceAddress) && (Completio= nEntry->EndPointAddress =3D=3D EndPointAddress)) { + CompletionEntry->Cancel =3D 1; + } + CompletionEntry =3D CompletionEntry->Next; + } + gBS->RestoreTPL (OriginalTPL); + return EFI_SUCCESS; + } + + CompletionEntry =3D AllocateZeroPool (sizeof(DWUSB_INTERRUPT_QUEUE)); + if (CompletionEntry =3D=3D NULL) { + DEBUG ((EFI_D_ERROR, "DwHcAsyncInterruptTransfer: failed to allocate buf= fer\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + CompletionEntry->Data =3D AllocateZeroPool (DataLength); + if (CompletionEntry->Data =3D=3D NULL) { + FreePool(CompletionEntry); + DEBUG ((EFI_D_ERROR, "DwHcAsyncInterruptTransfer: failed to allocate buf= fer\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; =20 + } + + CompletionEntry->CallBackFunction =3D CallBackFunction; + CompletionEntry->DataLength =3D DataLength; + CompletionEntry->Context =3D Context; + CompletionEntry->TransferResult =3D EFI_USB_NOERROR; + CompletionEntry->DeviceAddress =3D DeviceAddress; + CompletionEntry->EndPointAddress =3D EndPointAddress; + CompletionEntry->Cancel =3D 0; + CompletionEntry->This =3D This; + CompletionEntry->DeviceSpeed =3D DeviceSpeed; + CompletionEntry->MaximumPacketLength =3D MaximumPacketLength; + CompletionEntry->Translator =3D Translator; + if (PollingInterval > DW_USB_POLL_TIMER) { + CompletionEntry->TicksBeforeActive =3D (PollingInterval/DW_USB_POLL_TIME= R); + } else { + CompletionEntry->TicksBeforeActive =3D 1; + } + CompletionEntry->Ticks =3D -1; + + Status =3D EFI_SUCCESS; + + CompletionEntry->DataToggle =3D *DataToggle; + + DEBUG ((EFI_D_VERBOSE, "DwHcAsyncInterruptTransfer: Save off results of i= nterrupt transfer\n")); + // queue the result to be reported on the timer + OriginalTPL =3D gBS->RaiseTPL(TPL_HIGH_LEVEL); + CompletionEntry->Next =3D DwHc->InterruptQueue; + DwHc->InterruptQueue =3D CompletionEntry; + gBS->RestoreTPL (OriginalTPL); + + + + EXIT: + return Status; +} + +EFI_STATUS +EFIAPI +DwHcSyncInterruptTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((EFI_D_ERROR, "DwHcSyncInterruptTransfer Not Supported\n",__fun= c__)); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +DwHcIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_N= UM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +{ + DEBUG ((EFI_D_ERROR, "DwHcIsochronousTransfer Not Supported\n",__func_= _)); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +DwHcAsyncIsochronousTransfer ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_N= UM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context + ) +{ + DEBUG ((EFI_D_ERROR, "DwHcAsyncIsochronousTransfer Not Supported\n",__= func__)); + return EFI_UNSUPPORTED; +} + +/** + Supported Functions +**/ + +VOID +InitFslspClkSel ( + IN DWUSB_OTGHC_DEV *DwHc + ) +{ + UINT32 PhyClk; + DEBUG ((EFI_D_VERBOSE, "InitFslspClkSel \n",__func__)); + PhyClk =3D DWC2_HCFG_FSLSPCLKSEL_30_60_MHZ; + + MmioAndThenOr32 (DwHc->DwUsbBase + HCFG, + ~DWC2_HCFG_FSLSPCLKSEL_MASK, + PhyClk << DWC2_HCFG_FSLSPCLKSEL_OFFSET); + if (DwHc->AtFullSpeed) + { + MmioAndThenOr32 (DwHc->DwUsbBase + HCFG, + ~DWC2_HCFG_FSLSSUPP, + DWC2_HCFG_FSLSSUPP); + } +} =09 + + +/** + + Timer to submit periodic interrupt transfer, and invoke callbacks + + @param Event Event handle + @param Context Device private data + +**/ + +VOID +EFIAPI +DwHcTimerCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DWUSB_OTGHC_DEV *DwHc =3D (DWUSB_OTGHC_DEV *) Context; + EFI_TPL OriginalTPL; + DWUSB_INTERRUPT_QUEUE *CompletionEntry; + DWUSB_INTERRUPT_QUEUE *CompletionNext; + UINT32 ret =3D 0; + + OriginalTPL =3D gBS->RaiseTPL(TPL_HIGH_LEVEL); + if (DwHc->BulkActive>0) { + // This is a gentle hack=20 + // to avoid colliding requests + // for now. + DwHc->BulkActive--; + ret =3D 1; + } + gBS->RestoreTPL (OriginalTPL); + + if (ret) + return; + +// DEBUG ((EFI_D_ERROR, "DwHcTimerCallback TPL=3D%dn\n",OriginalTPL)); + + // pick off all queued items. + OriginalTPL =3D gBS->RaiseTPL(TPL_HIGH_LEVEL); + CompletionNext =3D DwHc->InterruptQueue; + //DwHc->InterruptQueue =3D NULL; + gBS->RestoreTPL (OriginalTPL); + + // perform callbacks on queued interrupt status + while (CompletionNext) { + DEBUG ((EFI_D_VERBOSE, "DwHcTimerCallbackn\n")); + CompletionEntry =3D CompletionNext; + CompletionNext =3D CompletionEntry->Next; + CompletionEntry->Ticks++; + if ((CompletionEntry->CallBackFunction) && ( CompletionEntry->Cancel =3D= =3D 0 ) && (CompletionEntry->Ticks > CompletionEntry->TicksBeforeActive)) + { + UINT32 Pid; + UINT8 TransferDirection; + UINT8 EpAddress; + EFI_STATUS Status; + EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator =3D CompletionEntry->= Translator; + UINTN DataLength; + UINT32 Timeout =3D DW_USB_POLL_INTERRUPT; + =09 + if ( CompletionEntry->DeviceAddress =3D=3D 1 ) + { + // fast timeouts on first hub port + Timeout =3D 10; + DEBUG ((EFI_D_VERBOSE, "DwHcTimerCallbackn Reset timer for addr1\n")); + } + + // ok execute thie + EpAddress =3D CompletionEntry->EndPointAddress & 0x0F; + TransferDirection =3D (CompletionEntry->EndPointAddress >> 7) & 0x01; + =09 + Pid =3D CompletionEntry->DataToggle; + DataLength =3D CompletionEntry->DataLength; + =09 + DEBUG ((EFI_D_VERBOSE, "DwHcTimerCallback message to addr=3D%d, EP=3D%= d Pid=3D%d\n",CompletionEntry->DeviceAddress, EpAddress, Pid)); + + Status =3D DwHcTransfer (DwHc, CompletionEntry->DeviceAddress, Completi= onEntry->MaximumPacketLength, &Pid, TransferDirection,=20 + CompletionEntry->Data, &DataLength, + EpAddress, DWC2_HCCHAR_EPTYPE_INTR, &CompletionEntry->TransferR= esult, 1, 0, CompletionEntry->DeviceSpeed, + Translator->TranslatorPortNumber, Translator->TranslatorHubAddr= ess, 1, Timeout); + + DEBUG ((EFI_D_VERBOSE, "DwHcTimerCallback Pid=3D%d\n", Pid)); + if (EFI_ERROR(Status)) + { + //DEBUG ((EFI_D_ERROR, "Consider canceling the transaction here?\n")); + if (CompletionEntry->TransferResult =3D=3D EFI_USB_ERR_NAK ) { + // NAK's are still successful transmission + // particularly for interrupt transfers + Status =3D EFI_USB_NOERROR; + } + + if (CompletionEntry->TransferResult =3D=3D (EFI_USB_ERR_SYSTEM+1) ) { + // overruns may still have data, lets pass it on + Status =3D EFI_USB_NOERROR; + //DataLength =3D CompletionEntry->DataLength; + //CompletionEntry->TransferResult =3D EFI_USB_NOERROR; + } + if (CompletionEntry->TransferResult =3D=3D EFI_USB_ERR_TIMEOUT) + { + // This actually appears to recovery everything correctly + // but does it really need recovery, or just a retry? + //DEBUG ((EFI_D_ERROR, "Doing full reset\n")); + // doing full reset + DwHcReset(CompletionEntry->This,0); + } + + } + =09 + CompletionEntry->DataToggle =3D Pid; + =09 + // don't report NAK's and DATA Toggle errors, what the end user doesn't= know won't kill them.. + if ((CompletionEntry->TransferResult !=3D EFI_USB_ERR_SYSTEM) && (Compl= etionEntry->TransferResult !=3D EFI_USB_ERR_NAK )) { + CompletionEntry->CallBackFunction (CompletionEntry->Data, DataLength, = CompletionEntry->Context, CompletionEntry->TransferResult); + } + CompletionEntry->Ticks =3D 0; //reset the ticks + } + } + + { + // Nove canceled items to a cancel list + // and then delete all the entries on the canceled list + DWUSB_INTERRUPT_QUEUE *Canceled; + // now remove any canceled entries + OriginalTPL =3D gBS->RaiseTPL(TPL_HIGH_LEVEL); + CompletionNext =3D DwHc->InterruptQueue; + DwHc->InterruptQueue =3D NULL; + Canceled =3D NULL; + =09 + while (CompletionNext) { + =09 + CompletionEntry =3D CompletionNext; + CompletionNext =3D CompletionEntry->Next; + if (CompletionEntry->Cancel) + { + // toss it on the canceled queue + CompletionEntry->Next =3D Canceled; + Canceled =3D CompletionEntry->Next; + } + else + { + // toss it back on the pending queue + CompletionEntry->Next =3D DwHc->InterruptQueue; + DwHc->InterruptQueue =3D CompletionEntry; + } + } + gBS->RestoreTPL (OriginalTPL); + + while (Canceled) + { + DEBUG ((EFI_D_VERBOSE, "DwHcTimerCallback cancel\n")); + CompletionEntry =3D Canceled; + Canceled =3D CompletionEntry->Next; + FreePool(CompletionEntry->Data); + FreePool(CompletionEntry); + } + } + +} + +VOID +DwHcInit ( + IN DWUSB_OTGHC_DEV *DwHc + ) +{ + UINT32 NpTxFifoSz =3D 0; + UINT32 pTxFifoSz =3D 0; + UINT32 Hprt0 =3D 0; + INT32 i, Status, NumChannels; + DEBUG ((EFI_D_VERBOSE, "HwHcInit \n",__func__)); + + MmioWrite32 (DwHc->DwUsbBase + PCGCCTL, 0); + + InitFslspClkSel (DwHc); + + MmioWrite32 (DwHc->DwUsbBase + GRXFSIZ, DWC2_HOST_RX_FIFO_SIZE); + + NpTxFifoSz |=3D DWC2_HOST_NPERIO_TX_FIFO_SIZE << DWC2_FIFOSIZE_DEPTH_O= FFSET; + NpTxFifoSz |=3D DWC2_HOST_RX_FIFO_SIZE << DWC2_FIFOSIZE_STARTADDR_OFFS= ET; + MmioWrite32 (DwHc->DwUsbBase + GNPTXFSIZ, NpTxFifoSz); + + pTxFifoSz |=3D DWC2_HOST_PERIO_TX_FIFO_SIZE << DWC2_FIFOSIZE_DEPTH_OFF= SET; + pTxFifoSz |=3D (DWC2_HOST_RX_FIFO_SIZE + DWC2_HOST_NPERIO_TX_FIFO_SIZE= ) << + DWC2_FIFOSIZE_STARTADDR_OFFSET; + MmioWrite32 (DwHc->DwUsbBase + HPTXFSIZ, pTxFifoSz); + + MmioAnd32 (DwHc->DwUsbBase + GOTGCTL, ~(DWC2_GOTGCTL_HSTSETHNPEN)); + + DwFlushTxFifo (DwHc, 0x10); + DwFlushRxFifo (DwHc); + + NumChannels =3D MmioRead32 (DwHc->DwUsbBase + GHWCFG2); + NumChannels &=3D DWC2_HWCFG2_NUM_HOST_CHAN_MASK; + NumChannels >>=3D DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET; + NumChannels +=3D 1; + + for (i=3D0; iDwUsbBase + HCCHAR(i), + ~(DWC2_HCCHAR_CHEN | DWC2_HCCHAR_EPDIR), + DWC2_HCCHAR_CHDIS); + + for (i=3D0; iDwUsbBase + HCCHAR(i), + ~DWC2_HCCHAR_EPDIR, + (DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS)); + Status =3D Wait4Bit (DwHc->DwUsbBase + HCCHAR(i), DWC2_HCCHAR_CHEN= , 0); + if (Status) + DEBUG ((EFI_D_VERBOSE, "DwHcInit: Timeout!\n")); + } + + if (MmioRead32 (DwHc->DwUsbBase + GINTSTS) & DWC2_GINTSTS_CURMODE_HOST= ) { + Hprt0 =3D MmioRead32 (DwHc->DwUsbBase + HPRT0); + Hprt0 &=3D ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET); + Hprt0 &=3D ~(DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG); + + if (!(Hprt0 & DWC2_HPRT0_PRTPWR)) { + Hprt0 |=3D DWC2_HPRT0_PRTPWR; + MmioWrite32 (DwHc->DwUsbBase + HPRT0, Hprt0); + } + } +} + +VOID +DwCoreInit ( + IN DWUSB_OTGHC_DEV *DwHc + ) +{ + UINT32 AhbCfg =3D 0; + UINT32 UsbCfg =3D 0; + DEBUG ((EFI_D_VERBOSE, "DwCoreInit \n")); + + UsbCfg =3D MmioRead32 (DwHc->DwUsbBase + GUSBCFG); + + UsbCfg |=3D DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV; + UsbCfg &=3D ~DWC2_GUSBCFG_TERM_SEL_DL_PULSE; + + MmioWrite32 (DwHc->DwUsbBase + GUSBCFG, UsbCfg); + + DwCoreReset (DwHc); + + UsbCfg &=3D ~(DWC2_GUSBCFG_ULPI_UTMI_SEL | DWC2_GUSBCFG_PHYIF); + UsbCfg |=3D CONFIG_DWC2_PHY_TYPE << DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET; + + UsbCfg &=3D ~DWC2_GUSBCFG_DDRSEL; + + MmioWrite32 (DwHc->DwUsbBase + GUSBCFG, UsbCfg); + + DwCoreReset (DwHc); + + UsbCfg =3D MmioRead32 (DwHc->DwUsbBase + GUSBCFG); + UsbCfg &=3D ~(DWC2_GUSBCFG_ULPI_FSLS | DWC2_GUSBCFG_ULPI_CLK_SUS_M); + if (DW_FORCE_HOST) { + UsbCfg |=3D DWC2_GUSBCFG_FORCEHOSTMODE;=20 + } + UsbCfg &=3D ~(DWC2_GUSBCFG_HNPCAP | DWC2_GUSBCFG_SRPCAP); //disable ho= st neg protocol and SRP + MmioWrite32 (DwHc->DwUsbBase + GUSBCFG, UsbCfg); + + DEBUG ((EFI_D_ERROR, "DwCoreInit USB cfg %X\n",UsbCfg)); + + AhbCfg |=3D DWC2_GAHBCFG_HBURSTLEN_INCR4; + AhbCfg |=3D DWC2_GAHBCFG_DMAENABLE; + + MmioWrite32 (DwHc->DwUsbBase + GAHBCFG, AhbCfg); +// MmioOr32 (DwHc->DwUsbBase + GUSBCFG, DWC2_GUSBCFG_HNPCAP | DWC2_GUSB= CFG_SRPCAP); //enable host negotiation, and session request (not wanted for= host mode) + +} + +DWUSB_OTGHC_DEV * +CreateDwUsbHc ( + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + DWUSB_OTGHC_DEV *DwHc; + UINT32 Channel; + DEBUG ((EFI_D_VERBOSE, "CreateDwUsbHc \n",__func__)); + + DwHc =3D AllocateZeroPool (sizeof(DWUSB_OTGHC_DEV)); + + if (DwHc =3D=3D NULL) { + return NULL; + } + + DwHc->Signature =3D DWUSB_OTGHC_DEV_SI= GNATURE; + DwHc->DwUsbOtgHc.GetCapability =3D DwHcGetCapability; + DwHc->DwUsbOtgHc.Reset =3D DwHcReset; + DwHc->DwUsbOtgHc.GetState =3D DwHcGetState; + DwHc->DwUsbOtgHc.SetState =3D DwHcSetState; + DwHc->DwUsbOtgHc.ControlTransfer =3D DwHcControlTransfe= r; + DwHc->DwUsbOtgHc.BulkTransfer =3D DwHcBulkTransfer; + DwHc->DwUsbOtgHc.AsyncInterruptTransfer =3D DwHcAsyncInterrupt= Transfer; + DwHc->DwUsbOtgHc.SyncInterruptTransfer =3D DwHcSyncInterruptT= ransfer; + DwHc->DwUsbOtgHc.IsochronousTransfer =3D DwHcIsochronousTra= nsfer; + DwHc->DwUsbOtgHc.AsyncIsochronousTransfer =3D DwHcAsyncIsochrono= usTransfer; + DwHc->DwUsbOtgHc.GetRootHubPortStatus =3D DwHcGetRootHubPort= Status; + DwHc->DwUsbOtgHc.SetRootHubPortFeature =3D DwHcSetRootHubPort= Feature; + DwHc->DwUsbOtgHc.ClearRootHubPortFeature =3D DwHcClearRootHubPo= rtFeature; + DwHc->DwUsbOtgHc.MajorRevision =3D 0x02; + DwHc->DwUsbOtgHc.MinorRevision =3D 0x00; + DwHc->DwUsbBase =3D FixedPcdGet32 (PcdDwUsbBaseAddress); //TOD= O remove this and convert to Pci->Mem.Read/Write() calls + + DwHc->InterruptQueue =3D NULL; + DwHc->PciIo =3D PciIo; + DwHc->BulkActive =3D 0; + DwHc->AtFullSpeed =3D DW_AT_FULLSPEED; + + for (Channel =3D 0 ; Channel < DWC2_MAX_CHANNELS; Channel++) + { + DwHc->ActiveChannel[Channel] =3D FALSE; + } + + + return DwHc; +} + +VOID +EFIAPI +DwUsbHcExitBootService ( + EFI_EVENT Event, + VOID *Context + ) +{ + DWUSB_OTGHC_DEV *DwHc; +=09 + DEBUG ((EFI_D_ERROR, "\n\n\nEXIT BOOT SERVICES!\n\n\n")); + + DwHc =3D (DWUSB_OTGHC_DEV *) Context; + + MmioAndThenOr32 (DwHc->DwUsbBase + HPRT0, + ~(DWC2_HPRT0_PRTENA | DWC2_HPRT0_PRTCONNDET | + DWC2_HPRT0_PRTENCHNG | DWC2_HPRT0_PRTOVRCURRCHNG), + DWC2_HPRT0_PRTRST); + + MicroSecondDelay (50000); + + DwCoreReset (DwHc); +} + +#pragma pack(1) +typedef struct { + UINT8 ProgInterface; + UINT8 SubClassCode; + UINT8 BaseCode; +} USB_CLASSC; +#pragma pack() + +/** + Test to see if this driver supports ControllerHandle. Any + ControllerHandle that has Usb2HcProtocol installed will + be supported. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath Not used. + + @return EFI_SUCCESS This driver supports this device. + @return EFI_UNSUPPORTED This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +DwUsbDriverBindingSupported ( + 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; + + // + // Test whether there is PCI IO Protocol attached on the controller handl= e. + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status =3D PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_CLASSCODE_OFFSET, + sizeof (USB_CLASSC) / sizeof (UINT8), + &UsbClassCReg + ); + + if (EFI_ERROR (Status)) { + Status =3D EFI_UNSUPPORTED; + goto ON_EXIT; + } + + // + // Test whether the controller belongs to Usb class type + // + if ((UsbClassCReg.BaseCode !=3D PCI_CLASS_SERIAL) || (UsbClassCReg.SubCla= ssCode !=3D PCI_CLASS_SERIAL_USB)) { + Status =3D EFI_UNSUPPORTED; + } + else { + DEBUG ((EFI_D_VERBOSE, "DwUsbDriverBindingSupported found board!\n")); + } + + ON_EXIT: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +DwUsbDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + DWUSB_OTGHC_DEV *DwHc; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *HcDevicePath; + + Status =3D EFI_SUCCESS; + + // + // Open the PciIo Protocol, then enable the USB host controller + // + Status =3D gBS->OpenProtocol ( Controller, + &gEfiPciIoProtocolGuid,=20 + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER ); + + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((EFI_D_VERBOSE, "DwUsbDriverBindingStart2 \n")); + // + // Open Device Path Protocol for on USB host controller + // + HcDevicePath =3D NULL; + Status =3D gBS->OpenProtocol ( Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &HcDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ); + DEBUG ((EFI_D_VERBOSE, "DwUsbDriverBindingStart3 \n")); + + if (EFI_ERROR (Status)) { + return Status; + } + + + DwHc =3D CreateDwUsbHc (PciIo); + + if (DwHc =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + DEBUG ((EFI_D_VERBOSE, "DwUsbDriverBindingStart4 \n")); + Status =3D gBS->InstallProtocolInterface ( &Controller, + &gEfiUsb2HcProtocolGuid, + EFI_NATIVE_INTERFACE, + &DwHc->DwUsbOtgHc ); + + DEBUG ((EFI_D_VERBOSE, "DwUsbDriverBindingStart5 \n")); + if (EFI_ERROR (Status)) { + goto UNINSTALL_PROTOCOL; + } + + DEBUG ((EFI_D_VERBOSE, "DwUsbDriverBindingStart6 \n")); + // + // Start the asynchronous interrupt monitor + // + Status =3D gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + DwHcTimerCallback, + DwHc, + &DwHc->PollTimer); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Failed to register DwUsbHostDxe Timer\n")); =09 + } + + Status =3D gBS->SetTimer (DwHc->PollTimer, TimerPeriodic, EFI_TIMER_PERIO= D_MILLISECONDS(DW_USB_POLL_TIMER)); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Failed to enable DwUsbHostDxe Timer\n")); =09 + } + + + Status =3D gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + DwUsbHcExitBootService, + DwHc, + &gEfiEventExitBootServicesGuid, + &DwHc->ExitBootServiceEvent ); + + if (EFI_ERROR (Status)) { + goto UNINSTALL_PROTOCOL; + } + + return Status; + + UNINSTALL_PROTOCOL: + FreePool (DwHc); + EXIT: + return Status; +} + +/** + Stop this driver on ControllerHandle. Support stopping any child handles + created by this driver. + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on. + @param NumberOfChildren Number of Children in the ChildHandleBuffe= r. + @param ChildHandleBuffer List of handles for the children we need t= o stop. + + @return EFI_SUCCESS Success. + @return EFI_DEVICE_ERROR Fail. + +**/ +EFI_STATUS +EFIAPI +DwUsbDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_USB2_HC_PROTOCOL *Usb2Hc; +// EFI_PCI_IO_PROTOCOL *PciIo; + DWUSB_OTGHC_DEV *DwHc; + + DEBUG ((EFI_D_ERROR, "DwUsbDriverBindingStop \n")); + // + // Test whether the Controller handler passed in is a valid + // Usb controller handle that should be supported, if not, + // return the error status directly + // + Status =3D gBS->OpenProtocol ( + Controller, + &gEfiUsb2HcProtocolGuid, + (VOID **) &Usb2Hc, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + DwHc =3D DWHC_FROM_THIS (This); + + Status =3D gBS->UninstallProtocolInterface ( + Controller, + &gEfiUsb2HcProtocolGuid, + DwHc + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Stop AsyncRequest Polling timer then stop the EHCI driver + // and uninstall the EHCI protocl. + // + + // stop the interrupt handing + Status =3D gBS->SetTimer (DwHc->PollTimer, TimerCancel, 0 ); + if (DwHc->PollTimer !=3D NULL) { + gBS->CloseEvent (DwHc->PollTimer); + } + =20 + if (DwHc->ExitBootServiceEvent !=3D NULL) { + gBS->CloseEvent (DwHc->ExitBootServiceEvent); + } + =20 +/* + EhcFreeSched (Ehc); + + if (Ehc->ControllerNameTable !=3D NULL) { + FreeUnicodeStringTable (Ehc->ControllerNameTable); + } +*/ + // + // Disable routing of all ports to EHCI controller, so all ports are=20 + // routed back to the UHCI or OHCI controller. + // + /*EhcClearOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC); + + // + // Restore original PCI attributes + // + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + Ehc->OriginalPciAttributes, + NULL + ); + */ + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + FreePool (DwHc); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DwUsbHostExitPoint ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + + return Status; +} + + +EFI_DRIVER_BINDING_PROTOCOL +gDwUsbDriverBinding =3D { + DwUsbDriverBindingSupported, + DwUsbDriverBindingStart, + DwUsbDriverBindingStop, + 0x30, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +DwUsbHostEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + DEBUG ((EFI_D_ERROR, "DwUsbEntryPoint \n")); + return EfiLibInstallDriverBindingComponentName2 (=20 + ImageHandle, + SystemTable, + &gDwUsbDriverBinding, + ImageHandle, + &gDwUsbComponentName, + &gDwUsbComponentName2 + ); +} diff --git a/Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.h b/Silicon/Syn= opsys/Usb/DwUsbHostDxe/DwUsbHostDxe.h new file mode 100644 index 000000000..e76094646 --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.h @@ -0,0 +1,121 @@ +/** @file + + Copyright (c) 2015-2016, Linaro Limited. All rights reserved. + Copyright (c) 2017, Jeremy Linton + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + + +#ifndef _DWUSBHOSTDXE_H_ +#define _DWUSBHOSTDXE_H_ + +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "DwcHw.h" + +#define MAX_DEVICE 16 +#define MAX_ENDPOINT 16 + +typedef struct _DWUSB_OTGHC_DEV DWUSB_OTGHC_DEV; + +#define DWUSB_OTGHC_DEV_SIGNATURE SIGNATURE_32 ('d', 'w', 'h', 'c') +#define DWHC_FROM_THIS(a) CR(a, DWUSB_OTGHC_DEV, DwUsbOtgHc, DWUSB_OTGHC_= DEV_SIGNATURE) + +extern EFI_DRIVER_BINDING_PROTOCOL gDwUsbDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gDwUsbComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gDwUsbComponentName2; + +// +// The RequestType in EFI_USB_DEVICE_REQUEST is composed of +// three fields: One bit direction, 2 bit type, and 5 bit +// target. +// +#define USB_REQUEST_TYPE(Dir, Type, Target) \ + ((UINT8)((((Dir) =3D=3D EfiUsbDataIn ? 0x01 : 0) << 7) | (Type) = | (Target))) + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + PCI_DEVICE_PATH PciDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} EFI_USB_PCIIO_DEVICE_PATH; + +typedef struct _DWUSB_INTERRUPT_QUEUE DWUSB_INTERRUPT_QUEUE; +struct _DWUSB_INTERRUPT_QUEUE { + DWUSB_INTERRUPT_QUEUE *Next; + EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction; + VOID *Data; + UINTN DataLength; + VOID *Context; + UINT32 TransferResult; + UINT8 DeviceAddress; //used for matchi= ng + UINT8 EndPointAddress; + UINT8 Cancel; +// Now everything needed to queue another interrupt transfer + EFI_USB2_HC_PROTOCOL *This; + UINT8 DeviceSpeed; + UINTN MaximumPacketLength; + EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator; + UINT8 DataToggle; + UINT32 TicksBeforeActive; + INT32 Ticks; +}; + +struct _DWUSB_OTGHC_DEV { + UINTN Signature; + EFI_HANDLE DeviceHandle; + + EFI_USB2_HC_PROTOCOL DwUsbOtgHc; + + EFI_USB_HC_STATE DwHcState; + + EFI_USB_PCIIO_DEVICE_PATH DevicePath; + + EFI_EVENT ExitBootServiceEvent; + + UINT64 DwUsbBase; + + UINT16 PortStatus; + UINT16 PortChangeStatus; + + UINT32 RhDevNum; + + EFI_EVENT PollTimer; //interrupt transfers require an async res= ponse model, use a timer to send the query/callback + DWUSB_INTERRUPT_QUEUE *InterruptQueue; //the queue of interrupt transfer = results + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + UINT32 BulkActive; + BOOLEAN AtFullSpeed; + BOOLEAN ActiveChannel[DWC2_MAX_CHANNELS]; +}; + +#endif //_DWUSBHOSTDXE_H_ diff --git a/Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.inf b/Silicon/S= ynopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.inf new file mode 100644 index 000000000..5a2109599 --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbHostDxe/DwUsbHostDxe.inf @@ -0,0 +1,61 @@ +#/** @file +# +# Copyright (c) 2015-2016, Linaro Limited. All rights reserved. +# Copyright (c) 2017, Jeremy Linton +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +# +# +#**/ + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D DwUsbHostDxe + FILE_GUID =3D 4bf1704c-03f4-46d5-bca6-82fa580badfd + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D DwUsbHostEntryPoint +# UNLOAD_IMAGE =3D DwUsbHostExitPoint + +[Sources.common] + DwUsbHostDxe.c + ComponentName.c + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Silicon/Synopsys/Usb/DwUsbDxe/DwUsbDxe.dec + +[LibraryClasses] + DmaLib + MemoryAllocationLib + BaseLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + BaseMemoryLib + DebugLib + PcdLib + ReportStatusCodeLib + TimerLib + IoLib + +[Guids] + gEfiEventExitBootServicesGuid + +[Protocols] + gEfiDriverBindingProtocolGuid + gEfiUsb2HcProtocolGuid + gEfiPciIoProtocolGuid ## TO_START + +[Pcd] + gDwUsbDxeTokenSpaceGuid.PcdDwUsbBaseAddress + gDwUsbDxeTokenSpaceGuid.PcdDwUsbSysCtrlBaseAddress + diff --git a/Silicon/Synopsys/Usb/DwUsbHostDxe/DwcHw.h b/Silicon/Synopsys/U= sb/DwUsbHostDxe/DwcHw.h new file mode 100644 index 000000000..fbe07f64b --- /dev/null +++ b/Silicon/Synopsys/Usb/DwUsbHostDxe/DwcHw.h @@ -0,0 +1,792 @@ +/** @file + + Copyright (c) 2015-2016, Linaro Limited. All rights reserved. + Copyright (c) 2017, Jeremy Linton + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#ifndef __DWCHW_H__ +#define __DWCHW_H__ + +#define HSOTG_REG(x) (x) + +#define HCCHAR(_ch) HSOTG_REG(0x0500 + 0x20 * (_ch)) +#define HCSPLT(_ch) HSOTG_REG(0x0504 + 0x20 * (_ch)) +#define HCINT(_ch) HSOTG_REG(0x0508 + 0x20 * (_ch)) +#define HCINTMSK(_ch) HSOTG_REG(0x050c + 0x20 * (_ch)) +#define HCTSIZ(_ch) HSOTG_REG(0x0510 + 0x20 * (_ch)) +#define HCDMA(_ch) HSOTG_REG(0x0514 + 0x20 * (_ch)) +#define HCDMAB(_ch) HSOTG_REG(0x051c + 0x20 * (_ch)) + +#define HCFG HSOTG_REG(0x0400) //Host Config +#define HFIR HSOTG_REG(0x0404) //Host Frame int= erval register +#define HFNUM HSOTG_REG(0x0408) //Host Frame num= ber/frame time +#define HPTXSTS HSOTG_REG(0x0410) //Host periodic = transmit fifo queue status reg +#define HAINT HSOTG_REG(0x0414) //Host all chann= el interrupt register +#define HAINTMSK HSOTG_REG(0x0418) //Host all chann= el interrupt mask +#define HFLBADDR HSOTG_REG(0x041c)=20 + +#define GOTGCTL HSOTG_REG(0x000) +#define GOTGINT HSOTG_REG(0x004) +#define GAHBCFG HSOTG_REG(0x008) +#define GUSBCFG HSOTG_REG(0x00C) //Global USB conf= ig +#define GRSTCTL HSOTG_REG(0x010) +#define GINTSTS HSOTG_REG(0x014) +#define GINTMSK HSOTG_REG(0x018) +#define GRXSTSR HSOTG_REG(0x01C) +#define GRXSTSP HSOTG_REG(0x020) +#define GRXFSIZ HSOTG_REG(0x024) +#define GNPTXFSIZ HSOTG_REG(0x028) +#define GNPTXSTS HSOTG_REG(0x02C) +#define GI2CCTL HSOTG_REG(0x0030) +#define GPVNDCTL HSOTG_REG(0x0034) +#define GGPIO HSOTG_REG(0x0038) +#define GUID HSOTG_REG(0x003c) +#define GSNPSID HSOTG_REG(0x0040) +#define GHWCFG1 HSOTG_REG(0x0044) +#define GHWCFG2 HSOTG_REG(0x0048) +#define GHWCFG3 HSOTG_REG(0x004c) +#define GHWCFG4 HSOTG_REG(0x0050) +#define GLPMCFG HSOTG_REG(0x0054) +#define HPTXFSIZ HSOTG_REG(0x100) +#define DPTXFSIZN(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4)) +#define HPRT0 HSOTG_REG(0x0440) +#define PCGCCTL HSOTG_REG(0xE00) + +#define DWC2_GOTGCTL_SESREQSCS (1 << 0) +#define DWC2_GOTGCTL_SESREQSCS_OFFSET 0 +#define DWC2_GOTGCTL_SESREQ (1 << 1) +#define DWC2_GOTGCTL_SESREQ_OFFSET 1 +#define DWC2_GOTGCTL_HSTNEGSCS (1 << 8) +#define DWC2_GOTGCTL_HSTNEGSCS_OFFSET 8 +#define DWC2_GOTGCTL_HNPREQ (1 << 9) +#define DWC2_GOTGCTL_HNPREQ_OFFSET 9 +#define DWC2_GOTGCTL_HSTSETHNPEN (1 << 10) +#define DWC2_GOTGCTL_HSTSETHNPEN_OFFSET 10 +#define DWC2_GOTGCTL_DEVHNPEN (1 << 11) +#define DWC2_GOTGCTL_DEVHNPEN_OFFSET 11 +#define DWC2_GOTGCTL_CONIDSTS (1 << 16) +#define DWC2_GOTGCTL_CONIDSTS_OFFSET 16 +#define DWC2_GOTGCTL_DBNCTIME (1 << 17) +#define DWC2_GOTGCTL_DBNCTIME_OFFSET 17 +#define DWC2_GOTGCTL_ASESVLD (1 << 18) +#define DWC2_GOTGCTL_ASESVLD_OFFSET 18 +#define DWC2_GOTGCTL_BSESVLD (1 << 19) +#define DWC2_GOTGCTL_BSESVLD_OFFSET 19 +#define DWC2_GOTGCTL_OTGVER (1 << 20) +#define DWC2_GOTGCTL_OTGVER_OFFSET 20 +#define DWC2_GOTGINT_SESENDDET (1 << 2) +#define DWC2_GOTGINT_SESENDDET_OFFSET 2 +#define DWC2_GOTGINT_SESREQSUCSTSCHNG (1 << 8) +#define DWC2_GOTGINT_SESREQSUCSTSCHNG_OFFSET 8 +#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG (1 << 9) +#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG_OFFSET 9 +#define DWC2_GOTGINT_RESERVER10_16_MASK (0x7F << 10) +#define DWC2_GOTGINT_RESERVER10_16_OFFSET 10 +#define DWC2_GOTGINT_HSTNEGDET (1 << 17) +#define DWC2_GOTGINT_HSTNEGDET_OFFSET 17 +#define DWC2_GOTGINT_ADEVTOUTCHNG (1 << 18) +#define DWC2_GOTGINT_ADEVTOUTCHNG_OFFSET 18 +#define DWC2_GOTGINT_DEBDONE (1 << 19) +#define DWC2_GOTGINT_DEBDONE_OFFSET 19 +#define DWC2_GAHBCFG_GLBLINTRMSK (1 << 0) +#define DWC2_GAHBCFG_GLBLINTRMSK_OFFSET 0 +#define DWC2_GAHBCFG_HBURSTLEN_SINGLE (0 << 1) +#define DWC2_GAHBCFG_HBURSTLEN_INCR (1 << 1) +#define DWC2_GAHBCFG_HBURSTLEN_INCR4 (3 << 1) +#define DWC2_GAHBCFG_HBURSTLEN_INCR8 (5 << 1) +#define DWC2_GAHBCFG_HBURSTLEN_INCR16 (7 << 1) +#define DWC2_GAHBCFG_HBURSTLEN_MASK (0xF << 1) +#define DWC2_GAHBCFG_HBURSTLEN_OFFSET 1 +#define DWC2_GAHBCFG_DMAENABLE (1 << 5) +#define DWC2_GAHBCFG_DMAENABLE_OFFSET 5 +#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL (1 << 7) +#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL_OFFSET 7 +#define DWC2_GAHBCFG_PTXFEMPLVL (1 << 8) +#define DWC2_GAHBCFG_PTXFEMPLVL_OFFSET 8 +#define DWC2_GUSBCFG_TOUTCAL_MASK (0x7 << 0) +#define DWC2_GUSBCFG_TOUTCAL_OFFSET 0 +#define DWC2_GUSBCFG_PHYIF (1 << 3) +#define DWC2_GUSBCFG_PHYIF_OFFSET 3 +#define DWC2_GUSBCFG_ULPI_UTMI_SEL (1 << 4) +#define DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET 4 +#define DWC2_GUSBCFG_FSINTF (1 << 5) +#define DWC2_GUSBCFG_FSINTF_OFFSET 5 +#define DWC2_GUSBCFG_PHYSEL (1 << 6) //Phy select (host only) 1 full sp= eed phy, 0 external hign speed +#define DWC2_GUSBCFG_PHYSEL_OFFSET 6 +#define DWC2_GUSBCFG_DDRSEL (1 << 7) +#define DWC2_GUSBCFG_DDRSEL_OFFSET 7 +#define DWC2_GUSBCFG_SRPCAP (1 << 8) +#define DWC2_GUSBCFG_SRPCAP_OFFSET 8 +#define DWC2_GUSBCFG_HNPCAP (1 << 9) +#define DWC2_GUSBCFG_HNPCAP_OFFSET 9 +#define DWC2_GUSBCFG_USBTRDTIM_MASK (0xF << 10) +#define DWC2_GUSBCFG_USBTRDTIM_OFFSET 10 +#define DWC2_GUSBCFG_NPTXFRWNDEN (1 << 14) +#define DWC2_GUSBCFG_NPTXFRWNDEN_OFFSET 14 +#define DWC2_GUSBCFG_PHYLPWRCLKSEL (1 << 15) +#define DWC2_GUSBCFG_PHYLPWRCLKSEL_OFFSET 15 +#define DWC2_GUSBCFG_OTGUTMIFSSEL (1 << 16) +#define DWC2_GUSBCFG_OTGUTMIFSSEL_OFFSET 16 +#define DWC2_GUSBCFG_ULPI_FSLS (1 << 17) +#define DWC2_GUSBCFG_ULPI_FSLS_OFFSET 17 +#define DWC2_GUSBCFG_ULPI_AUTO_RES (1 << 18) +#define DWC2_GUSBCFG_ULPI_AUTO_RES_OFFSET 18 +#define DWC2_GUSBCFG_ULPI_CLK_SUS_M (1 << 19) +#define DWC2_GUSBCFG_ULPI_CLK_SUS_M_OFFSET 19 +#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV (1 << 20) +#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV_OFFSET 20 +#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR (1 << 21) +#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR_OFFSET 21 +#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE (1 << 22) +#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE_OFFSET 22 +#define DWC2_GUSBCFG_IC_USB_CAP (1 << 26) +#define DWC2_GUSBCFG_IC_USB_CAP_OFFSET 26 +#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE (1 << 27) +#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE_OFFSET 27 +#define DWC2_GUSBCFG_TX_END_DELAY (1 << 28) +#define DWC2_GUSBCFG_TX_END_DELAY_OFFSET 28 +#define DWC2_GUSBCFG_FORCEHOSTMODE (1 << 29) //force host mode +#define DWC2_GUSBCFG_FORCEHOSTMODE_OFFSET 29 +#define DWC2_GUSBCFG_FORCEDEVMODE (1 << 30) //force device mode +#define DWC2_GUSBCFG_FORCEDEVMODE_OFFSET 30 +#define DWC2_GLPMCTL_LPM_CAP_EN (1 << 0) +#define DWC2_GLPMCTL_LPM_CAP_EN_OFFSET 0 +#define DWC2_GLPMCTL_APPL_RESP (1 << 1) +#define DWC2_GLPMCTL_APPL_RESP_OFFSET 1 +#define DWC2_GLPMCTL_HIRD_MASK (0xF << 2) +#define DWC2_GLPMCTL_HIRD_OFFSET 2 +#define DWC2_GLPMCTL_REM_WKUP_EN (1 << 6) +#define DWC2_GLPMCTL_REM_WKUP_EN_OFFSET 6 +#define DWC2_GLPMCTL_EN_UTMI_SLEEP (1 << 7) +#define DWC2_GLPMCTL_EN_UTMI_SLEEP_OFFSET 7 +#define DWC2_GLPMCTL_HIRD_THRES_MASK (0x1F << 8) +#define DWC2_GLPMCTL_HIRD_THRES_OFFSET 8 +#define DWC2_GLPMCTL_LPM_RESP_MASK (0x3 << 13) +#define DWC2_GLPMCTL_LPM_RESP_OFFSET 13 +#define DWC2_GLPMCTL_PRT_SLEEP_STS (1 << 15) +#define DWC2_GLPMCTL_PRT_SLEEP_STS_OFFSET 15 +#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK (1 << 16) +#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK_OFFSET 16 +#define DWC2_GLPMCTL_LPM_CHAN_INDEX_MASK (0xF << 17) +#define DWC2_GLPMCTL_LPM_CHAN_INDEX_OFFSET 17 +#define DWC2_GLPMCTL_RETRY_COUNT_MASK (0x7 << 21) +#define DWC2_GLPMCTL_RETRY_COUNT_OFFSET 21 +#define DWC2_GLPMCTL_SEND_LPM (1 << 24) +#define DWC2_GLPMCTL_SEND_LPM_OFFSET 24 +#define DWC2_GLPMCTL_RETRY_COUNT_STS_MASK (0x7 << 25) +#define DWC2_GLPMCTL_RETRY_COUNT_STS_OFFSET 25 +#define DWC2_GLPMCTL_HSIC_CONNECT (1 << 30) +#define DWC2_GLPMCTL_HSIC_CONNECT_OFFSET 30 +#define DWC2_GLPMCTL_INV_SEL_HSIC (1 << 31) +#define DWC2_GLPMCTL_INV_SEL_HSIC_OFFSET 31 +#define DWC2_GRSTCTL_CSFTRST (1 << 0) +#define DWC2_GRSTCTL_CSFTRST_OFFSET 0 +#define DWC2_GRSTCTL_HSFTRST (1 << 1) +#define DWC2_GRSTCTL_HSFTRST_OFFSET 1 +#define DWC2_GRSTCTL_HSTFRM (1 << 2) +#define DWC2_GRSTCTL_HSTFRM_OFFSET 2 +#define DWC2_GRSTCTL_INTKNQFLSH (1 << 3) +#define DWC2_GRSTCTL_INTKNQFLSH_OFFSET 3 +#define DWC2_GRSTCTL_RXFFLSH (1 << 4) +#define DWC2_GRSTCTL_RXFFLSH_OFFSET 4 +#define DWC2_GRSTCTL_TXFFLSH (1 << 5) +#define DWC2_GRSTCTL_TXFFLSH_OFFSET 5 +#define DWC2_GRSTCTL_TXFNUM_MASK (0x1F << 6) +#define DWC2_GRSTCTL_TXFNUM_OFFSET 6 +#define DWC2_GRSTCTL_DMAREQ (1 << 30) +#define DWC2_GRSTCTL_DMAREQ_OFFSET 30 +#define DWC2_GRSTCTL_AHBIDLE (1 << 31) +#define DWC2_GRSTCTL_AHBIDLE_OFFSET 31 +#define DWC2_GINTMSK_MODEMISMATCH (1 << 1) +#define DWC2_GINTMSK_MODEMISMATCH_OFFSET 1 +#define DWC2_GINTMSK_OTGINTR (1 << 2) +#define DWC2_GINTMSK_OTGINTR_OFFSET 2 +#define DWC2_GINTMSK_SOFINTR (1 << 3) +#define DWC2_GINTMSK_SOFINTR_OFFSET 3 +#define DWC2_GINTMSK_RXSTSQLVL (1 << 4) +#define DWC2_GINTMSK_RXSTSQLVL_OFFSET 4 +#define DWC2_GINTMSK_NPTXFEMPTY (1 << 5) +#define DWC2_GINTMSK_NPTXFEMPTY_OFFSET 5 +#define DWC2_GINTMSK_GINNAKEFF (1 << 6) +#define DWC2_GINTMSK_GINNAKEFF_OFFSET 6 +#define DWC2_GINTMSK_GOUTNAKEFF (1 << 7) +#define DWC2_GINTMSK_GOUTNAKEFF_OFFSET 7 +#define DWC2_GINTMSK_I2CINTR (1 << 9) +#define DWC2_GINTMSK_I2CINTR_OFFSET 9 +#define DWC2_GINTMSK_ERLYSUSPEND (1 << 10) +#define DWC2_GINTMSK_ERLYSUSPEND_OFFSET 10 +#define DWC2_GINTMSK_USBSUSPEND (1 << 11) +#define DWC2_GINTMSK_USBSUSPEND_OFFSET 11 +#define DWC2_GINTMSK_USBRESET (1 << 12) +#define DWC2_GINTMSK_USBRESET_OFFSET 12 +#define DWC2_GINTMSK_ENUMDONE (1 << 13) +#define DWC2_GINTMSK_ENUMDONE_OFFSET 13 +#define DWC2_GINTMSK_ISOOUTDROP (1 << 14) +#define DWC2_GINTMSK_ISOOUTDROP_OFFSET 14 +#define DWC2_GINTMSK_EOPFRAME (1 << 15) +#define DWC2_GINTMSK_EOPFRAME_OFFSET 15 +#define DWC2_GINTMSK_EPMISMATCH (1 << 17) +#define DWC2_GINTMSK_EPMISMATCH_OFFSET 17 +#define DWC2_GINTMSK_INEPINTR (1 << 18) +#define DWC2_GINTMSK_INEPINTR_OFFSET 18 +#define DWC2_GINTMSK_OUTEPINTR (1 << 19) +#define DWC2_GINTMSK_OUTEPINTR_OFFSET 19 +#define DWC2_GINTMSK_INCOMPLISOIN (1 << 20) +#define DWC2_GINTMSK_INCOMPLISOIN_OFFSET 20 +#define DWC2_GINTMSK_INCOMPLISOOUT (1 << 21) +#define DWC2_GINTMSK_INCOMPLISOOUT_OFFSET 21 +#define DWC2_GINTMSK_PORTINTR (1 << 24) +#define DWC2_GINTMSK_PORTINTR_OFFSET 24 +#define DWC2_GINTMSK_HCINTR (1 << 25) +#define DWC2_GINTMSK_HCINTR_OFFSET 25 +#define DWC2_GINTMSK_PTXFEMPTY (1 << 26) +#define DWC2_GINTMSK_PTXFEMPTY_OFFSET 26 +#define DWC2_GINTMSK_LPMTRANRCVD (1 << 27) +#define DWC2_GINTMSK_LPMTRANRCVD_OFFSET 27 +#define DWC2_GINTMSK_CONIDSTSCHNG (1 << 28) +#define DWC2_GINTMSK_CONIDSTSCHNG_OFFSET 28 +#define DWC2_GINTMSK_DISCONNECT (1 << 29) +#define DWC2_GINTMSK_DISCONNECT_OFFSET 29 +#define DWC2_GINTMSK_SESSREQINTR (1 << 30) +#define DWC2_GINTMSK_SESSREQINTR_OFFSET 30 +#define DWC2_GINTMSK_WKUPINTR (1 << 31) +#define DWC2_GINTMSK_WKUPINTR_OFFSET 31 +#define DWC2_GINTSTS_CURMODE_DEVICE (0 << 0) +#define DWC2_GINTSTS_CURMODE_HOST (1 << 0) +#define DWC2_GINTSTS_CURMODE (1 << 0) +#define DWC2_GINTSTS_CURMODE_OFFSET 0 +#define DWC2_GINTSTS_MODEMISMATCH (1 << 1) +#define DWC2_GINTSTS_MODEMISMATCH_OFFSET 1 +#define DWC2_GINTSTS_OTGINTR (1 << 2) +#define DWC2_GINTSTS_OTGINTR_OFFSET 2 +#define DWC2_GINTSTS_SOFINTR (1 << 3) +#define DWC2_GINTSTS_SOFINTR_OFFSET 3 +#define DWC2_GINTSTS_RXSTSQLVL (1 << 4) +#define DWC2_GINTSTS_RXSTSQLVL_OFFSET 4 +#define DWC2_GINTSTS_NPTXFEMPTY (1 << 5) +#define DWC2_GINTSTS_NPTXFEMPTY_OFFSET 5 +#define DWC2_GINTSTS_GINNAKEFF (1 << 6) +#define DWC2_GINTSTS_GINNAKEFF_OFFSET 6 +#define DWC2_GINTSTS_GOUTNAKEFF (1 << 7) +#define DWC2_GINTSTS_GOUTNAKEFF_OFFSET 7 +#define DWC2_GINTSTS_I2CINTR (1 << 9) +#define DWC2_GINTSTS_I2CINTR_OFFSET 9 +#define DWC2_GINTSTS_ERLYSUSPEND (1 << 10) +#define DWC2_GINTSTS_ERLYSUSPEND_OFFSET 10 +#define DWC2_GINTSTS_USBSUSPEND (1 << 11) +#define DWC2_GINTSTS_USBSUSPEND_OFFSET 11 +#define DWC2_GINTSTS_USBRESET (1 << 12) +#define DWC2_GINTSTS_USBRESET_OFFSET 12 +#define DWC2_GINTSTS_ENUMDONE (1 << 13) +#define DWC2_GINTSTS_ENUMDONE_OFFSET 13 +#define DWC2_GINTSTS_ISOOUTDROP (1 << 14) +#define DWC2_GINTSTS_ISOOUTDROP_OFFSET 14 +#define DWC2_GINTSTS_EOPFRAME (1 << 15) +#define DWC2_GINTSTS_EOPFRAME_OFFSET 15 +#define DWC2_GINTSTS_INTOKENRX (1 << 16) +#define DWC2_GINTSTS_INTOKENRX_OFFSET 16 +#define DWC2_GINTSTS_EPMISMATCH (1 << 17) +#define DWC2_GINTSTS_EPMISMATCH_OFFSET 17 +#define DWC2_GINTSTS_INEPINT (1 << 18) +#define DWC2_GINTSTS_INEPINT_OFFSET 18 +#define DWC2_GINTSTS_OUTEPINTR (1 << 19) +#define DWC2_GINTSTS_OUTEPINTR_OFFSET 19 +#define DWC2_GINTSTS_INCOMPLISOIN (1 << 20) +#define DWC2_GINTSTS_INCOMPLISOIN_OFFSET 20 +#define DWC2_GINTSTS_INCOMPLISOOUT (1 << 21) +#define DWC2_GINTSTS_INCOMPLISOOUT_OFFSET 21 +#define DWC2_GINTSTS_PORTINTR (1 << 24) +#define DWC2_GINTSTS_PORTINTR_OFFSET 24 +#define DWC2_GINTSTS_HCINTR (1 << 25) +#define DWC2_GINTSTS_HCINTR_OFFSET 25 +#define DWC2_GINTSTS_PTXFEMPTY (1 << 26) +#define DWC2_GINTSTS_PTXFEMPTY_OFFSET 26 +#define DWC2_GINTSTS_LPMTRANRCVD (1 << 27) +#define DWC2_GINTSTS_LPMTRANRCVD_OFFSET 27 +#define DWC2_GINTSTS_CONIDSTSCHNG (1 << 28) +#define DWC2_GINTSTS_CONIDSTSCHNG_OFFSET 28 +#define DWC2_GINTSTS_DISCONNECT (1 << 29) +#define DWC2_GINTSTS_DISCONNECT_OFFSET 29 +#define DWC2_GINTSTS_SESSREQINTR (1 << 30) +#define DWC2_GINTSTS_SESSREQINTR_OFFSET 30 +#define DWC2_GINTSTS_WKUPINTR (1 << 31) +#define DWC2_GINTSTS_WKUPINTR_OFFSET 31 +#define DWC2_GRXSTS_EPNUM_MASK (0xF << 0) +#define DWC2_GRXSTS_EPNUM_OFFSET 0 +#define DWC2_GRXSTS_BCNT_MASK (0x7FF << 4) +#define DWC2_GRXSTS_BCNT_OFFSET 4 +#define DWC2_GRXSTS_DPID_MASK (0x3 << 15) +#define DWC2_GRXSTS_DPID_OFFSET 15 +#define DWC2_GRXSTS_PKTSTS_MASK (0xF << 17) +#define DWC2_GRXSTS_PKTSTS_OFFSET 17 +#define DWC2_GRXSTS_FN_MASK (0xF << 21) +#define DWC2_GRXSTS_FN_OFFSET 21 +#define DWC2_FIFOSIZE_STARTADDR_MASK (0xFFFF << 0) +#define DWC2_FIFOSIZE_STARTADDR_OFFSET 0 +#define DWC2_FIFOSIZE_DEPTH_MASK (0xFFFF << 16) +#define DWC2_FIFOSIZE_DEPTH_OFFSET 16 +#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_MASK (0xFFFF << 0) +#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_OFFSET 0 +#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_MASK (0xFF << 16) +#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_OFFSET 16 +#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE (1 << 24) +#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE_OFFSET 24 +#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_MASK (0x3 << 25) +#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_OFFSET 25 +#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_MASK (0xF << 27) +#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_OFFSET 27 +#define DWC2_DTXFSTS_TXFSPCAVAIL_MASK (0xFFFF << 0) +#define DWC2_DTXFSTS_TXFSPCAVAIL_OFFSET 0 +#define DWC2_GI2CCTL_RWDATA_MASK (0xFF << 0) +#define DWC2_GI2CCTL_RWDATA_OFFSET 0 +#define DWC2_GI2CCTL_REGADDR_MASK (0xFF << 8) +#define DWC2_GI2CCTL_REGADDR_OFFSET 8 +#define DWC2_GI2CCTL_ADDR_MASK (0x7F << 16) +#define DWC2_GI2CCTL_ADDR_OFFSET 16 +#define DWC2_GI2CCTL_I2CEN (1 << 23) +#define DWC2_GI2CCTL_I2CEN_OFFSET 23 +#define DWC2_GI2CCTL_ACK (1 << 24) +#define DWC2_GI2CCTL_ACK_OFFSET 24 +#define DWC2_GI2CCTL_I2CSUSPCTL (1 << 25) +#define DWC2_GI2CCTL_I2CSUSPCTL_OFFSET 25 +#define DWC2_GI2CCTL_I2CDEVADDR_MASK (0x3 << 26) +#define DWC2_GI2CCTL_I2CDEVADDR_OFFSET 26 +#define DWC2_GI2CCTL_RW (1 << 30) +#define DWC2_GI2CCTL_RW_OFFSET 30 +#define DWC2_GI2CCTL_BSYDNE (1 << 31) +#define DWC2_GI2CCTL_BSYDNE_OFFSET 31 +#define DWC2_HWCFG1_EP_DIR0_MASK (0x3 << 0) +#define DWC2_HWCFG1_EP_DIR0_OFFSET 0 +#define DWC2_HWCFG1_EP_DIR1_MASK (0x3 << 2) +#define DWC2_HWCFG1_EP_DIR1_OFFSET 2 +#define DWC2_HWCFG1_EP_DIR2_MASK (0x3 << 4) +#define DWC2_HWCFG1_EP_DIR2_OFFSET 4 +#define DWC2_HWCFG1_EP_DIR3_MASK (0x3 << 6) +#define DWC2_HWCFG1_EP_DIR3_OFFSET 6 +#define DWC2_HWCFG1_EP_DIR4_MASK (0x3 << 8) +#define DWC2_HWCFG1_EP_DIR4_OFFSET 8 +#define DWC2_HWCFG1_EP_DIR5_MASK (0x3 << 10) +#define DWC2_HWCFG1_EP_DIR5_OFFSET 10 +#define DWC2_HWCFG1_EP_DIR6_MASK (0x3 << 12) +#define DWC2_HWCFG1_EP_DIR6_OFFSET 12 +#define DWC2_HWCFG1_EP_DIR7_MASK (0x3 << 14) +#define DWC2_HWCFG1_EP_DIR7_OFFSET 14 +#define DWC2_HWCFG1_EP_DIR8_MASK (0x3 << 16) +#define DWC2_HWCFG1_EP_DIR8_OFFSET 16 +#define DWC2_HWCFG1_EP_DIR9_MASK (0x3 << 18) +#define DWC2_HWCFG1_EP_DIR9_OFFSET 18 +#define DWC2_HWCFG1_EP_DIR10_MASK (0x3 << 20) +#define DWC2_HWCFG1_EP_DIR10_OFFSET 20 +#define DWC2_HWCFG1_EP_DIR11_MASK (0x3 << 22) +#define DWC2_HWCFG1_EP_DIR11_OFFSET 22 +#define DWC2_HWCFG1_EP_DIR12_MASK (0x3 << 24) +#define DWC2_HWCFG1_EP_DIR12_OFFSET 24 +#define DWC2_HWCFG1_EP_DIR13_MASK (0x3 << 26) +#define DWC2_HWCFG1_EP_DIR13_OFFSET 26 +#define DWC2_HWCFG1_EP_DIR14_MASK (0x3 << 28) +#define DWC2_HWCFG1_EP_DIR14_OFFSET 28 +#define DWC2_HWCFG1_EP_DIR15_MASK (0x3 << 30) +#define DWC2_HWCFG1_EP_DIR15_OFFSET 30 +#define DWC2_HWCFG2_OP_MODE_MASK (0x7 << 0) +#define DWC2_HWCFG2_OP_MODE_OFFSET 0 +#define DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY (0x0 << 3) +#define DWC2_HWCFG2_ARCHITECTURE_EXT_DMA (0x1 << 3) +#define DWC2_HWCFG2_ARCHITECTURE_INT_DMA (0x2 << 3) +#define DWC2_HWCFG2_ARCHITECTURE_MASK (0x3 << 3) +#define DWC2_HWCFG2_ARCHITECTURE_OFFSET 3 +#define DWC2_HWCFG2_POINT2POINT (1 << 5) +#define DWC2_HWCFG2_POINT2POINT_OFFSET 5 +#define DWC2_HWCFG2_HS_PHY_TYPE_MASK (0x3 << 6) +#define DWC2_HWCFG2_HS_PHY_TYPE_OFFSET 6 +#define DWC2_HWCFG2_FS_PHY_TYPE_MASK (0x3 << 8) +#define DWC2_HWCFG2_FS_PHY_TYPE_OFFSET 8 +#define DWC2_HWCFG2_NUM_DEV_EP_MASK (0xF << 10) +#define DWC2_HWCFG2_NUM_DEV_EP_OFFSET 10 +#define DWC2_HWCFG2_NUM_HOST_CHAN_MASK (0xF << 14) +#define DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET 14 +#define DWC2_HWCFG2_PERIO_EP_SUPPORTED (1 << 18) +#define DWC2_HWCFG2_PERIO_EP_SUPPORTED_OFFSET 18 +#define DWC2_HWCFG2_DYNAMIC_FIFO (1 << 19) +#define DWC2_HWCFG2_DYNAMIC_FIFO_OFFSET 19 +#define DWC2_HWCFG2_MULTI_PROC_INT (1 << 20) +#define DWC2_HWCFG2_MULTI_PROC_INT_OFFSET 20 +#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22) +#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_OFFSET 22 +#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24) +#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_OFFSET 24 +#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1F << 26) +#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_OFFSET 26 +#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xF << 0) +#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_OFFSET 0 +#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4) +#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_OFFSET 4 +#define DWC2_HWCFG3_OTG_FUNC (1 << 7) +#define DWC2_HWCFG3_OTG_FUNC_OFFSET 7 +#define DWC2_HWCFG3_I2C (1 << 8) +#define DWC2_HWCFG3_I2C_OFFSET 8 +#define DWC2_HWCFG3_VENDOR_CTRL_IF (1 << 9) +#define DWC2_HWCFG3_VENDOR_CTRL_IF_OFFSET 9 +#define DWC2_HWCFG3_OPTIONAL_FEATURES (1 << 10) +#define DWC2_HWCFG3_OPTIONAL_FEATURES_OFFSET 10 +#define DWC2_HWCFG3_SYNCH_RESET_TYPE (1 << 11) +#define DWC2_HWCFG3_SYNCH_RESET_TYPE_OFFSET 11 +#define DWC2_HWCFG3_OTG_ENABLE_IC_USB (1 << 12) +#define DWC2_HWCFG3_OTG_ENABLE_IC_USB_OFFSET 12 +#define DWC2_HWCFG3_OTG_ENABLE_HSIC (1 << 13) +#define DWC2_HWCFG3_OTG_ENABLE_HSIC_OFFSET 13 +#define DWC2_HWCFG3_OTG_LPM_EN (1 << 15) +#define DWC2_HWCFG3_OTG_LPM_EN_OFFSET 15 +#define DWC2_HWCFG3_DFIFO_DEPTH_MASK (0xFFFF << 16) +#define DWC2_HWCFG3_DFIFO_DEPTH_OFFSET 16 +#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xF << 0) +#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_OFFSET 0 +#define DWC2_HWCFG4_POWER_OPTIMIZ (1 << 4) +#define DWC2_HWCFG4_POWER_OPTIMIZ_OFFSET 4 +#define DWC2_HWCFG4_MIN_AHB_FREQ_MASK (0x1FF << 5) +#define DWC2_HWCFG4_MIN_AHB_FREQ_OFFSET 5 +#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) +#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_OFFSET 14 +#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xF << 16) +#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_OFFSET 16 +#define DWC2_HWCFG4_IDDIG_FILT_EN (1 << 20) +#define DWC2_HWCFG4_IDDIG_FILT_EN_OFFSET 20 +#define DWC2_HWCFG4_VBUS_VALID_FILT_EN (1 << 21) +#define DWC2_HWCFG4_VBUS_VALID_FILT_EN_OFFSET 21 +#define DWC2_HWCFG4_A_VALID_FILT_EN (1 << 22) +#define DWC2_HWCFG4_A_VALID_FILT_EN_OFFSET 22 +#define DWC2_HWCFG4_B_VALID_FILT_EN (1 << 23) +#define DWC2_HWCFG4_B_VALID_FILT_EN_OFFSET 23 +#define DWC2_HWCFG4_SESSION_END_FILT_EN (1 << 24) +#define DWC2_HWCFG4_SESSION_END_FILT_EN_OFFSET 24 +#define DWC2_HWCFG4_DED_FIFO_EN (1 << 25) +#define DWC2_HWCFG4_DED_FIFO_EN_OFFSET 25 +#define DWC2_HWCFG4_NUM_IN_EPS_MASK (0xF << 26) +#define DWC2_HWCFG4_NUM_IN_EPS_OFFSET 26 +#define DWC2_HWCFG4_DESC_DMA (1 << 30) +#define DWC2_HWCFG4_DESC_DMA_OFFSET 30 +#define DWC2_HWCFG4_DESC_DMA_DYN (1 << 31) +#define DWC2_HWCFG4_DESC_DMA_DYN_OFFSET 31 +#define DWC2_HCFG_FSLSPCLKSEL_30_60_MHZ 0 +#define DWC2_HCFG_FSLSPCLKSEL_48_MHZ 1 +#define DWC2_HCFG_FSLSPCLKSEL_6_MHZ 2 +#define DWC2_HCFG_FSLSPCLKSEL_MASK (0x3 << 0) +#define DWC2_HCFG_FSLSPCLKSEL_OFFSET 0 +#define DWC2_HCFG_FSLSSUPP (1 << 2) //Force core to enumerate at FS/LS = mode +#define DWC2_HCFG_FSLSSUPP_OFFSET 2 +#define DWC2_HCFG_DESCDMA (1 << 23) +#define DWC2_HCFG_DESCDMA_OFFSET 23 +#define DWC2_HCFG_FRLISTEN_MASK (0x3 << 24) +#define DWC2_HCFG_FRLISTEN_OFFSET 24 +#define DWC2_HCFG_PERSCHEDENA (1 << 26) +#define DWC2_HCFG_PERSCHEDENA_OFFSET 26 +#define DWC2_HCFG_PERSCHEDSTAT (1 << 27) +#define DWC2_HCFG_PERSCHEDSTAT_OFFSET 27 +#define DWC2_HFIR_FRINT_MASK (0xFFFF << 0) +#define DWC2_HFIR_FRINT_OFFSET 0 +#define DWC2_HFNUM_FRNUM_MASK (0xFFFF << 0) +#define DWC2_HFNUM_FRNUM_OFFSET 0 +#define DWC2_HFNUM_FRREM_MASK (0xFFFF << 16) +#define DWC2_HFNUM_FRREM_OFFSET 16 +#define DWC2_HPTXSTS_PTXFSPCAVAIL_MASK (0xFFFF << 0) +#define DWC2_HPTXSTS_PTXFSPCAVAIL_OFFSET 0 +#define DWC2_HPTXSTS_PTXQSPCAVAIL_MASK (0xFF << 16) +#define DWC2_HPTXSTS_PTXQSPCAVAIL_OFFSET 16 +#define DWC2_HPTXSTS_PTXQTOP_TERMINATE (1 << 24) +#define DWC2_HPTXSTS_PTXQTOP_TERMINATE_OFFSET 24 +#define DWC2_HPTXSTS_PTXQTOP_TOKEN_MASK (0x3 << 25) +#define DWC2_HPTXSTS_PTXQTOP_TOKEN_OFFSET 25 +#define DWC2_HPTXSTS_PTXQTOP_CHNUM_MASK (0xF << 27) +#define DWC2_HPTXSTS_PTXQTOP_CHNUM_OFFSET 27 +#define DWC2_HPTXSTS_PTXQTOP_ODD (1 << 31) +#define DWC2_HPTXSTS_PTXQTOP_ODD_OFFSET 31 +#define DWC2_HPRT0_PRTCONNSTS (1 << 0) +#define DWC2_HPRT0_PRTCONNSTS_OFFSET 0 +#define DWC2_HPRT0_PRTCONNDET (1 << 1) +#define DWC2_HPRT0_PRTCONNDET_OFFSET 1 +#define DWC2_HPRT0_PRTENA (1 << 2) +#define DWC2_HPRT0_PRTENA_OFFSET 2 +#define DWC2_HPRT0_PRTENCHNG (1 << 3) +#define DWC2_HPRT0_PRTENCHNG_OFFSET 3 +#define DWC2_HPRT0_PRTOVRCURRACT (1 << 4) +#define DWC2_HPRT0_PRTOVRCURRACT_OFFSET 4 +#define DWC2_HPRT0_PRTOVRCURRCHNG (1 << 5) +#define DWC2_HPRT0_PRTOVRCURRCHNG_OFFSET 5 +#define DWC2_HPRT0_PRTRES (1 << 6) +#define DWC2_HPRT0_PRTRES_OFFSET 6 +#define DWC2_HPRT0_PRTSUSP (1 << 7) +#define DWC2_HPRT0_PRTSUSP_OFFSET 7 +#define DWC2_HPRT0_PRTRST (1 << 8) +#define DWC2_HPRT0_PRTRST_OFFSET 8 +#define DWC2_HPRT0_PRTLNSTS_MASK (0x3 << 10) +#define DWC2_HPRT0_PRTLNSTS_OFFSET 10 +#define DWC2_HPRT0_PRTPWR (1 << 12) +#define DWC2_HPRT0_PRTPWR_OFFSET 12 +#define DWC2_HPRT0_PRTTSTCTL_MASK (0xF << 13) +#define DWC2_HPRT0_PRTTSTCTL_OFFSET 13 +#define DWC2_HPRT0_PRTSPD_MASK (0x3 << 17) +#define DWC2_HPRT0_PRTSPD_OFFSET 17 +#define DWC2_HAINT_CH0 (1 << 0) +#define DWC2_HAINT_CH0_OFFSET 0 +#define DWC2_HAINT_CH1 (1 << 1) +#define DWC2_HAINT_CH1_OFFSET 1 +#define DWC2_HAINT_CH2 (1 << 2) +#define DWC2_HAINT_CH2_OFFSET 2 +#define DWC2_HAINT_CH3 (1 << 3) +#define DWC2_HAINT_CH3_OFFSET 3 +#define DWC2_HAINT_CH4 (1 << 4) +#define DWC2_HAINT_CH4_OFFSET 4 +#define DWC2_HAINT_CH5 (1 << 5) +#define DWC2_HAINT_CH5_OFFSET 5 +#define DWC2_HAINT_CH6 (1 << 6) +#define DWC2_HAINT_CH6_OFFSET 6 +#define DWC2_HAINT_CH7 (1 << 7) +#define DWC2_HAINT_CH7_OFFSET 7 +#define DWC2_HAINT_CH8 (1 << 8) +#define DWC2_HAINT_CH8_OFFSET 8 +#define DWC2_HAINT_CH9 (1 << 9) +#define DWC2_HAINT_CH9_OFFSET 9 +#define DWC2_HAINT_CH10 (1 << 10) +#define DWC2_HAINT_CH10_OFFSET 10 +#define DWC2_HAINT_CH11 (1 << 11) +#define DWC2_HAINT_CH11_OFFSET 11 +#define DWC2_HAINT_CH12 (1 << 12) +#define DWC2_HAINT_CH12_OFFSET 12 +#define DWC2_HAINT_CH13 (1 << 13) +#define DWC2_HAINT_CH13_OFFSET 13 +#define DWC2_HAINT_CH14 (1 << 14) +#define DWC2_HAINT_CH14_OFFSET 14 +#define DWC2_HAINT_CH15 (1 << 15) +#define DWC2_HAINT_CH15_OFFSET 15 +#define DWC2_HAINT_CHINT_MASK 0xffff +#define DWC2_HAINT_CHINT_OFFSET 0 +#define DWC2_HAINTMSK_CH0 (1 << 0) +#define DWC2_HAINTMSK_CH0_OFFSET 0 +#define DWC2_HAINTMSK_CH1 (1 << 1) +#define DWC2_HAINTMSK_CH1_OFFSET 1 +#define DWC2_HAINTMSK_CH2 (1 << 2) +#define DWC2_HAINTMSK_CH2_OFFSET 2 +#define DWC2_HAINTMSK_CH3 (1 << 3) +#define DWC2_HAINTMSK_CH3_OFFSET 3 +#define DWC2_HAINTMSK_CH4 (1 << 4) +#define DWC2_HAINTMSK_CH4_OFFSET 4 +#define DWC2_HAINTMSK_CH5 (1 << 5) +#define DWC2_HAINTMSK_CH5_OFFSET 5 +#define DWC2_HAINTMSK_CH6 (1 << 6) +#define DWC2_HAINTMSK_CH6_OFFSET 6 +#define DWC2_HAINTMSK_CH7 (1 << 7) +#define DWC2_HAINTMSK_CH7_OFFSET 7 +#define DWC2_HAINTMSK_CH8 (1 << 8) +#define DWC2_HAINTMSK_CH8_OFFSET 8 +#define DWC2_HAINTMSK_CH9 (1 << 9) +#define DWC2_HAINTMSK_CH9_OFFSET 9 +#define DWC2_HAINTMSK_CH10 (1 << 10) +#define DWC2_HAINTMSK_CH10_OFFSET 10 +#define DWC2_HAINTMSK_CH11 (1 << 11) +#define DWC2_HAINTMSK_CH11_OFFSET 11 +#define DWC2_HAINTMSK_CH12 (1 << 12) +#define DWC2_HAINTMSK_CH12_OFFSET 12 +#define DWC2_HAINTMSK_CH13 (1 << 13) +#define DWC2_HAINTMSK_CH13_OFFSET 13 +#define DWC2_HAINTMSK_CH14 (1 << 14) +#define DWC2_HAINTMSK_CH14_OFFSET 14 +#define DWC2_HAINTMSK_CH15 (1 << 15) +#define DWC2_HAINTMSK_CH15_OFFSET 15 +#define DWC2_HAINTMSK_CHINT_MASK 0xffff +#define DWC2_HAINTMSK_CHINT_OFFSET 0 +#define DWC2_HCCHAR_MPS_MASK (0x7FF << 0) +#define DWC2_HCCHAR_MPS_OFFSET 0 +#define DWC2_HCCHAR_EPNUM_MASK (0xF << 11) +#define DWC2_HCCHAR_EPNUM_OFFSET 11 +#define DWC2_HCCHAR_EPDIR (1 << 15) +#define DWC2_HCCHAR_EPDIR_OFFSET 15 +#define DWC2_HCCHAR_LSPDDEV (1 << 17) +#define DWC2_HCCHAR_LSPDDEV_OFFSET 17 +#define DWC2_HCCHAR_EPTYPE_CONTROL 0 +#define DWC2_HCCHAR_EPTYPE_ISOC 1 +#define DWC2_HCCHAR_EPTYPE_BULK 2 +#define DWC2_HCCHAR_EPTYPE_INTR 3 +#define DWC2_HCCHAR_EPTYPE_MASK (0x3 << 18) +#define DWC2_HCCHAR_EPTYPE_OFFSET 18 +#define DWC2_HCCHAR_MULTICNT_MASK (0x3 << 20) +#define DWC2_HCCHAR_MULTICNT_OFFSET 20 +#define DWC2_HCCHAR_DEVADDR_MASK (0x7F << 22) +#define DWC2_HCCHAR_DEVADDR_OFFSET 22 +#define DWC2_HCCHAR_ODDFRM (1 << 29) +#define DWC2_HCCHAR_ODDFRM_OFFSET 29 +#define DWC2_HCCHAR_CHDIS (1 << 30) +#define DWC2_HCCHAR_CHDIS_OFFSET 30 +#define DWC2_HCCHAR_CHEN (1 << 31) +#define DWC2_HCCHAR_CHEN_OFFSET 31 +#define DWC2_HCSPLT_PRTADDR_MASK (0x7F << 0) +#define DWC2_HCSPLT_PRTADDR_OFFSET 0 +#define DWC2_HCSPLT_HUBADDR_MASK (0x7F << 7) +#define DWC2_HCSPLT_HUBADDR_OFFSET 7 +#define DWC2_HCSPLT_XACTPOS_MASK (0x3 << 14) +#define DWC2_HCSPLT_XACTPOS_MID 0 +#define DWC2_HCSPLT_XACTPOS_END 1 //otherwise each transactio= n needs to indicate if its beginning/mid/end +#define DWC2_HCSPLT_XACTPOS_BEGIN 2 +#define DWC2_HCSPLT_XACTPOS_ALL 3 //Xact all, is for complete= transactions < 188 bytes +#define DWC2_HCSPLT_XACTPOS_OFFSET 14 +#define DWC2_HCSPLT_COMPSPLT (1 << 16) //Do complete split, (request ho= st to do the complete split transaction) +#define DWC2_HCSPLT_COMPSPLT_OFFSET 16 +#define DWC2_HCSPLT_SPLTENA (1 << 31) +#define DWC2_HCSPLT_SPLTENA_OFFSET 31 +#define DWC2_HCINT_XFERCOMP (1 << 0) +#define DWC2_HCINT_XFERCOMP_OFFSET 0 +#define DWC2_HCINT_CHHLTD (1 << 1) //Channel Halt +#define DWC2_HCINT_CHHLTD_OFFSET 1 +#define DWC2_HCINT_AHBERR (1 << 2) +#define DWC2_HCINT_AHBERR_OFFSET 2 +#define DWC2_HCINT_STALL (1 << 3) +#define DWC2_HCINT_STALL_OFFSET 3 +#define DWC2_HCINT_NAK (1 << 4) +#define DWC2_HCINT_NAK_OFFSET 4 +#define DWC2_HCINT_ACK (1 << 5) +#define DWC2_HCINT_ACK_OFFSET 5 +#define DWC2_HCINT_NYET (1 << 6) +#define DWC2_HCINT_NYET_OFFSET 6 +#define DWC2_HCINT_XACTERR (1 << 7) +#define DWC2_HCINT_XACTERR_OFFSET 7 +#define DWC2_HCINT_BBLERR (1 << 8) +#define DWC2_HCINT_BBLERR_OFFSET 8 +#define DWC2_HCINT_FRMOVRUN (1 << 9) +#define DWC2_HCINT_FRMOVRUN_OFFSET 9 +#define DWC2_HCINT_DATATGLERR (1 << 10) +#define DWC2_HCINT_DATATGLERR_OFFSET 10 +#define DWC2_HCINT_BNA (1 << 11) +#define DWC2_HCINT_BNA_OFFSET 11 +#define DWC2_HCINT_XCS_XACT (1 << 12) +#define DWC2_HCINT_XCS_XACT_OFFSET 12 +#define DWC2_HCINT_FRM_LIST_ROLL (1 << 13) +#define DWC2_HCINT_FRM_LIST_ROLL_OFFSET 13 +#define DWC2_HCINTMSK_XFERCOMPL (1 << 0) +#define DWC2_HCINTMSK_XFERCOMPL_OFFSET 0 +#define DWC2_HCINTMSK_CHHLTD (1 << 1) +#define DWC2_HCINTMSK_CHHLTD_OFFSET 1 +#define DWC2_HCINTMSK_AHBERR (1 << 2) +#define DWC2_HCINTMSK_AHBERR_OFFSET 2 +#define DWC2_HCINTMSK_STALL (1 << 3) +#define DWC2_HCINTMSK_STALL_OFFSET 3 +#define DWC2_HCINTMSK_NAK (1 << 4) +#define DWC2_HCINTMSK_NAK_OFFSET 4 +#define DWC2_HCINTMSK_ACK (1 << 5) +#define DWC2_HCINTMSK_ACK_OFFSET 5 +#define DWC2_HCINTMSK_NYET (1 << 6) +#define DWC2_HCINTMSK_NYET_OFFSET 6 +#define DWC2_HCINTMSK_XACTERR (1 << 7) +#define DWC2_HCINTMSK_XACTERR_OFFSET 7 +#define DWC2_HCINTMSK_BBLERR (1 << 8) +#define DWC2_HCINTMSK_BBLERR_OFFSET 8 +#define DWC2_HCINTMSK_FRMOVRUN (1 << 9) +#define DWC2_HCINTMSK_FRMOVRUN_OFFSET 9 +#define DWC2_HCINTMSK_DATATGLERR (1 << 10) +#define DWC2_HCINTMSK_DATATGLERR_OFFSET 10 +#define DWC2_HCINTMSK_BNA (1 << 11) +#define DWC2_HCINTMSK_BNA_OFFSET 11 +#define DWC2_HCINTMSK_XCS_XACT (1 << 12) +#define DWC2_HCINTMSK_XCS_XACT_OFFSET 12 +#define DWC2_HCINTMSK_FRM_LIST_ROLL (1 << 13) +#define DWC2_HCINTMSK_FRM_LIST_ROLL_OFFSET 13 +#define DWC2_HCTSIZ_XFERSIZE_MASK 0x7ffff +#define DWC2_HCTSIZ_XFERSIZE_OFFSET 0 +#define DWC2_HCTSIZ_SCHINFO_MASK 0xff +#define DWC2_HCTSIZ_SCHINFO_OFFSET 0 +#define DWC2_HCTSIZ_NTD_MASK (0xff << 8) +#define DWC2_HCTSIZ_NTD_OFFSET 8 +#define DWC2_HCTSIZ_PKTCNT_MASK (0x3ff << 19) +#define DWC2_HCTSIZ_PKTCNT_OFFSET 19 +#define DWC2_HCTSIZ_PID_MASK (0x3 << 29) +#define DWC2_HCTSIZ_PID_OFFSET 29 +#define DWC2_HCTSIZ_DOPNG (1 << 31) +#define DWC2_HCTSIZ_DOPNG_OFFSET 31 +#define DWC2_HCDMA_CTD_MASK (0xFF << 3) +#define DWC2_HCDMA_CTD_OFFSET 3 +#define DWC2_HCDMA_DMA_ADDR_MASK (0x1FFFFF << 11) +#define DWC2_HCDMA_DMA_ADDR_OFFSET 11 +#define DWC2_PCGCCTL_STOPPCLK (1 << 0) +#define DWC2_PCGCCTL_STOPPCLK_OFFSET 0 +#define DWC2_PCGCCTL_GATEHCLK (1 << 1) +#define DWC2_PCGCCTL_GATEHCLK_OFFSET 1 +#define DWC2_PCGCCTL_PWRCLMP (1 << 2) +#define DWC2_PCGCCTL_PWRCLMP_OFFSET 2 +#define DWC2_PCGCCTL_RSTPDWNMODULE (1 << 3) +#define DWC2_PCGCCTL_RSTPDWNMODULE_OFFSET 3 +#define DWC2_PCGCCTL_PHYSUSPENDED (1 << 4) +#define DWC2_PCGCCTL_PHYSUSPENDED_OFFSET 4 +#define DWC2_PCGCCTL_ENBL_SLEEP_GATING (1 << 5) +#define DWC2_PCGCCTL_ENBL_SLEEP_GATING_OFFSET 5 +#define DWC2_PCGCCTL_PHY_IN_SLEEP (1 << 6) +#define DWC2_PCGCCTL_PHY_IN_SLEEP_OFFSET 6 +#define DWC2_PCGCCTL_DEEP_SLEEP (1 << 7) +#define DWC2_PCGCCTL_DEEP_SLEEP_OFFSET 7 +#define DWC2_SNPSID_DEVID_VER_2xx (0x4f542 << 12) +#define DWC2_SNPSID_DEVID_VER_3xx (0x4f543 << 12) +#define DWC2_SNPSID_DEVID_MASK (0xfffff << 12) +#define DWC2_SNPSID_DEVID_OFFSET 12 + +/* Host controller specific */ +#define DWC2_HC_PID_DATA0 0 +#define DWC2_HC_PID_DATA2 1 +#define DWC2_HC_PID_DATA1 2 +#define DWC2_HC_PID_MDATA 3 +#define DWC2_HC_PID_SETUP 3 + +/* roothub.a masks */ +#define RH_A_NDP (0xff << 0) /* number of downstream ports */ +#define RH_A_PSM (1 << 8) /* power switching mode */ +#define RH_A_NPS (1 << 9) /* no power switching */ +#define RH_A_DT (1 << 10) /* device type (mbz) */ +#define RH_A_OCPM (1 << 11) /* over current protection mode */ +#define RH_A_NOCP (1 << 12) /* no over current protection */ +#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ + +/* roothub.b masks */ +#define RH_B_DR 0x0000ffff /* device removable flags */ +#define RH_B_PPCM 0xffff0000 /* port power control mask */ + +#define DWC2_PHY_TYPE_FS 0 +#define DWC2_PHY_TYPE_UTMI 1 +#define DWC2_PHY_TYPE_ULPI 2 +#define CONFIG_DWC2_PHY_TYPE DWC2_PHY_TYPE_UTMI /* PHY type */ +#define CONFIG_DWC2_UTMI_WIDTH 8 /* UTMI bus width (8/16) */ + +#define DWC2_DMA_BURST_SIZE 32 /* DMA burst len */ +//#define DWC2_MAX_CHANNELS 16 /* Max # of EPs */ +#define DWC2_MAX_CHANNELS 12 /* Max # of EPs (12 for L= S/FS)*/ +#define DWC2_HOST_RX_FIFO_SIZE (516 + DWC2_MAX_CHANNELS) +#define DWC2_HOST_NPERIO_TX_FIFO_SIZE 0x100 /* nPeriodic TX FIFO */ +#define DWC2_HOST_PERIO_TX_FIFO_SIZE 0x200 /* Periodic TX FIFO */ +#define DWC2_MAX_TRANSFER_SIZE 65535 +#define DWC2_MAX_PACKET_COUNT 511 + +#define DWC2_HC_CHANNEL 0 + +#define DWC2_STATUS_BUF_SIZE 64 +#define DWC2_DATA_BUF_SIZE (64 * 1024) + + +#define USB_PORT_FEAT_CONNECTION 0 +#define USB_PORT_FEAT_ENABLE 1 +#define USB_PORT_FEAT_SUSPEND 2 +#define USB_PORT_FEAT_OVER_CURRENT 3 +#define USB_PORT_FEAT_RESET 4 +#define USB_PORT_FEAT_POWER 8 +#define USB_PORT_FEAT_LOWSPEED 9 +#define USB_PORT_FEAT_HIGHSPEED 10 +#define USB_PORT_FEAT_C_CONNECTION 16 +#define USB_PORT_FEAT_C_ENABLE 17 +#define USB_PORT_FEAT_C_SUSPEND 18 +#define USB_PORT_FEAT_C_OVER_CURRENT 19 +#define USB_PORT_FEAT_C_RESET 20 +#define USB_PORT_FEAT_TEST 21 + +#endif /* __DWCHW_H__ */ --=20 2.15.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel