v1. * Enable Android Fastboot App on HiKey platform.
Haojian Zhuang (9): Platforms/Hisilicon/HiKey: append more register definitions Platforms/Hisilicon/HiKey: add HiKey variable space Drivers/Usb/DwUsb: support designware usb Platforms/Hisilicon/HiKey: append GUID in dec Platforms/Hisilicon/HiKey: support GPIO controller Platforms/Hisilicon/HiKey: support designware USB controller Platforms/Hisilicon/HiKey: support fastboot driver Platforms/Hisilicon/HiKey: add platform boot manager Platforms/Hisilicon/HiKey: enable Android Fastboot
Chips/Hisilicon/Hi6220/Include/Hi6220.h | 29 + Drivers/Usb/DwUsbDxe/DwUsbDxe.c | 796 +++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.dec | 46 ++ Drivers/Usb/DwUsbDxe/DwUsbDxe.h | 627 ++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.inf | 52 ++ Include/Protocol/DwUsb.h | 81 +++ OpenPlatformPkg.dec | 1 + Platforms/Hisilicon/HiKey/HiKey.dec | 3 + Platforms/Hisilicon/HiKey/HiKey.dsc | 18 +- Platforms/Hisilicon/HiKey/HiKey.fdf | 6 +- .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c | 705 ++++++++++++++++++ .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf | 61 ++ .../Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c | 68 ++ .../Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf | 37 + .../Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c | 266 +++++++ .../Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf | 46 ++ .../Hisilicon/HiKey/Include/Guid/HiKeyVariable.h | 24 + .../Library/PlatformBootManagerLib/PlatformBm.c | 485 +++++++++++++ .../Library/PlatformBootManagerLib/PlatformBm.h | 59 ++ .../PlatformBootManagerLib.inf | 88 +++ .../Library/PlatformBootManagerLib/QuietBoot.c | 680 ++++++++++++++++++ 21 files changed, 4175 insertions(+), 3 deletions(-) create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.c create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.dec create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.h create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.inf create mode 100644 Include/Protocol/DwUsb.h create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf create mode 100644 Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf create mode 100644 Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf create mode 100644 Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h create mode 100644 Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c create mode 100644 Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.h create mode 100644 Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf create mode 100644 Platforms/Hisilicon/Library/PlatformBootManagerLib/QuietBoot.c
Add more register definitions in Hi6220 SoC.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org --- Chips/Hisilicon/Hi6220/Include/Hi6220.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/Chips/Hisilicon/Hi6220/Include/Hi6220.h b/Chips/Hisilicon/Hi6220/Include/Hi6220.h index 203424a..0bc270e 100644 --- a/Chips/Hisilicon/Hi6220/Include/Hi6220.h +++ b/Chips/Hisilicon/Hi6220/Include/Hi6220.h @@ -48,15 +48,41 @@ #define SC_PERIPH_CLKDIS0 0x204 #define SC_PERIPH_CLKSTAT0 0x208
+#define SC_PERIPH_CLKEN3 0x230 +#define SC_PERIPH_RSTEN3 0x330 #define SC_PERIPH_RSTEN0 0x300 #define SC_PERIPH_RSTDIS0 0x304 #define SC_PERIPH_RSTSTAT0 0x308 +#define SC_PERIPH_RSTDIS3 0x334 +#define SC_PERIPH_RSTSTAT3 0x338
#define RST0_USBOTG_BUS BIT4 #define RST0_POR_PICOPHY BIT5 #define RST0_USBOTG BIT6 #define RST0_USBOTG_32K BIT7
+/* SC_PERIPH_RSTEN0/RSTDIS0/RSTSTAT0 */ +#define PERIPH_RST0_MMC2 (1 << 2) + +/* SC_PERIPH_RSTEN3/RSTDIS3/RSTSTAT3 */ +#define PERIPH_RST3_CSSYS (1 << 0) +#define PERIPH_RST3_I2C0 (1 << 1) +#define PERIPH_RST3_I2C1 (1 << 2) +#define PERIPH_RST3_I2C2 (1 << 3) +#define PERIPH_RST3_I2C3 (1 << 4) +#define PERIPH_RST3_UART1 (1 << 5) +#define PERIPH_RST3_UART2 (1 << 6) +#define PERIPH_RST3_UART3 (1 << 7) +#define PERIPH_RST3_UART4 (1 << 8) +#define PERIPH_RST3_SSP (1 << 9) +#define PERIPH_RST3_PWM (1 << 10) +#define PERIPH_RST3_BLPWM (1 << 11) +#define PERIPH_RST3_TSENSOR (1 << 12) +#define PERIPH_RST3_DAPB (1 << 18) +#define PERIPH_RST3_HKADC (1 << 19) +#define PERIPH_RST3_CODEC_SSI (1 << 20) +#define PERIPH_RST3_PMUSSI1 (1 << 22) + #define EYE_PATTERN_PARA 0x7053348c
#define MDDRC_AXI_BASE 0xF7120000 @@ -74,4 +100,7 @@
#define PMUSSI_BASE 0xF8000000
+#define PMUSSI_REG(x) (PMUSSI_BASE + ((x) << 2)) + + #endif /* __HI6220_H__ */
On Sat, Feb 04, 2017 at 01:13:46PM +0800, Haojian Zhuang wrote:
Add more register definitions in Hi6220 SoC.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org
Chips/Hisilicon/Hi6220/Include/Hi6220.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/Chips/Hisilicon/Hi6220/Include/Hi6220.h b/Chips/Hisilicon/Hi6220/Include/Hi6220.h index 203424a..0bc270e 100644 --- a/Chips/Hisilicon/Hi6220/Include/Hi6220.h +++ b/Chips/Hisilicon/Hi6220/Include/Hi6220.h @@ -48,15 +48,41 @@ #define SC_PERIPH_CLKDIS0 0x204 #define SC_PERIPH_CLKSTAT0 0x208 +#define SC_PERIPH_CLKEN3 0x230 +#define SC_PERIPH_RSTEN3 0x330
Can this be inserted numerically sorted? (after SC_PERIPH_RSTSTAT0)
#define SC_PERIPH_RSTEN0 0x300 #define SC_PERIPH_RSTDIS0 0x304 #define SC_PERIPH_RSTSTAT0 0x308 +#define SC_PERIPH_RSTDIS3 0x334 +#define SC_PERIPH_RSTSTAT3 0x338 #define RST0_USBOTG_BUS BIT4 #define RST0_POR_PICOPHY BIT5 #define RST0_USBOTG BIT6 #define RST0_USBOTG_32K BIT7 +/* SC_PERIPH_RSTEN0/RSTDIS0/RSTSTAT0 */ +#define PERIPH_RST0_MMC2 (1 << 2)
+/* SC_PERIPH_RSTEN3/RSTDIS3/RSTSTAT3 */ +#define PERIPH_RST3_CSSYS (1 << 0) +#define PERIPH_RST3_I2C0 (1 << 1) +#define PERIPH_RST3_I2C1 (1 << 2) +#define PERIPH_RST3_I2C2 (1 << 3) +#define PERIPH_RST3_I2C3 (1 << 4) +#define PERIPH_RST3_UART1 (1 << 5) +#define PERIPH_RST3_UART2 (1 << 6) +#define PERIPH_RST3_UART3 (1 << 7) +#define PERIPH_RST3_UART4 (1 << 8) +#define PERIPH_RST3_SSP (1 << 9) +#define PERIPH_RST3_PWM (1 << 10) +#define PERIPH_RST3_BLPWM (1 << 11) +#define PERIPH_RST3_TSENSOR (1 << 12) +#define PERIPH_RST3_DAPB (1 << 18) +#define PERIPH_RST3_HKADC (1 << 19) +#define PERIPH_RST3_CODEC_SSI (1 << 20) +#define PERIPH_RST3_PMUSSI1 (1 << 22)
#define EYE_PATTERN_PARA 0x7053348c #define MDDRC_AXI_BASE 0xF7120000 @@ -74,4 +100,7 @@ #define PMUSSI_BASE 0xF8000000 +#define PMUSSI_REG(x) (PMUSSI_BASE + ((x) << 2))
#endif /* __HI6220_H__ */
2.7.4
Create HiKey variable space to store variables.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org --- .../Hisilicon/HiKey/Include/Guid/HiKeyVariable.h | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h
diff --git a/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h new file mode 100644 index 0000000..32d51f9 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h @@ -0,0 +1,24 @@ +/** @file +* +* Copyright (c) 2013-2014, ARM Limited. All rights reserved. +* Copyright (c) 2015-2016, Linaro. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#ifndef __HIKEY_VARIABLE_H__ +#define __HIKEY_VARIABLE_H__ + +#define HIKEY_VARIABLE_GUID \ + { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } + +extern EFI_GUID gHiKeyVariableGuid; + +#endif /* __HIKEY_VARIABLE_H__ */
Support Designware USB controller.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org --- Drivers/Usb/DwUsbDxe/DwUsbDxe.c | 796 ++++++++++++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.dec | 46 +++ Drivers/Usb/DwUsbDxe/DwUsbDxe.h | 627 ++++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.inf | 52 +++ Include/Protocol/DwUsb.h | 81 ++++ 5 files changed, 1602 insertions(+) create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.c create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.dec create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.h create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.inf create mode 100644 Include/Protocol/DwUsb.h
diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.c b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c new file mode 100644 index 0000000..bdd8405 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c @@ -0,0 +1,796 @@ +/** @file + + Copyright (c) 2015-2017, Linaro. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <IndustryStandard/Usb.h> +#include <Library/ArmLib.h> +#include <Library/TimerLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UncachedMemoryAllocationLib.h> +#include <Library/CacheMaintenanceLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/BaseLib.h> +#include <Protocol/DwUsb.h> +#include <Protocol/UsbDevice.h> + +#include "DwUsbDxe.h" + +#define USB_TYPE_LENGTH 16 +#define USB_BLOCK_HIGH_SPEED_SIZE 512 +#define DATA_SIZE 32768 +#define CMD_SIZE 512 +#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1) + +// The time between interrupt polls, in units of 100 nanoseconds +// 10 Microseconds +#define DW_INTERRUPT_POLL_PERIOD 10000 + +EFI_GUID gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID; + +STATIC dwc_otg_dev_dma_desc_t *gDmaDesc,*gDmaDescEp0,*gDmaDescIn; +STATIC USB_DEVICE_REQUEST *gCtrlReq; +STATIC VOID *RxBuf; +STATIC UINTN RxDescBytes = 0; +STATIC UINTN mNumDataBytes; + +STATIC DW_USB_PROTOCOL *DwUsb; + +STATIC USB_DEVICE_DESCRIPTOR *mDeviceDescriptor; + +// The config descriptor, interface descriptor, and endpoint descriptors in 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; + + +/* To detect which mode was run, high speed or full speed */ +STATIC +UINTN +UsbDrvPortSpeed ( + VOID + ) +{ + /* + * 2'b00: High speed (PHY clock is running at 30 or 60 MHz) + */ + UINT32 Val = READ_REG32 (DSTS) & 2; + return (!Val); +} + +STATIC +VOID +ResetEndpoints ( + VOID + ) +{ + /* EP0 IN ACTIVE NEXT=1 */ + WRITE_REG32 (DIEPCTL0, DXEPCTL_USBACTEP | BIT11); + + /* EP0 OUT ACTIVE */ + WRITE_REG32 (DOEPCTL0, DXEPCTL_USBACTEP); + + /* Clear any pending OTG Interrupts */ + WRITE_REG32 (GOTGINT, ~0); + + /* Clear any pending interrupts */ + WRITE_REG32 (GINTSTS, ~0); + WRITE_REG32 (DIEPINT0, ~0); + WRITE_REG32 (DOEPINT0, ~0); + WRITE_REG32 (DIEPINT1, ~0); + WRITE_REG32 (DOEPINT1, ~0); + + /* IN EP interrupt mask */ + WRITE_REG32 (DIEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK); + /* OUT EP interrupt mask */ + WRITE_REG32 (DOEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK); + /* Enable interrupts on Ep0 */ + WRITE_REG32 (DAINTMSK, (1 << DAINTMSK_OUTEPMSK_SHIFT) | (1 << DAINTMSK_INEPMSK_SHIFT)); + + /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/ + WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64)); + + //notes that:the compulsive conversion is expectable. + gDmaDescEp0->status.b.bs = 0x3; + gDmaDescEp0->status.b.mtrf = 0; + gDmaDescEp0->status.b.sr = 0; + gDmaDescEp0->status.b.l = 1; + gDmaDescEp0->status.b.ioc = 1; + gDmaDescEp0->status.b.sp = 0; + gDmaDescEp0->status.b.bytes = 64; + gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq); + gDmaDescEp0->status.b.sts = 0; + gDmaDescEp0->status.b.bs = 0x0; + WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0)); + /* EP0 OUT ENABLE CLEARNAK */ + WRITE_REG32 (DOEPCTL0, (READ_REG32 (DOEPCTL0) | DXEPCTL_EPENA | DXEPCTL_CNAK)); +} + +STATIC +VOID +EpTx ( + IN UINT8 Ep, + IN CONST VOID *Ptr, + IN UINTN Len + ) +{ + UINT32 BlockSize; + UINT32 Packets; + + /* EPx OUT ACTIVE */ + WRITE_REG32 (DIEPCTL (Ep), (READ_REG32 (DIEPCTL (Ep))) | DXEPCTL_USBACTEP); + if (!Ep) { + BlockSize = 64; + } else { + BlockSize = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64; + } + Packets = (Len + BlockSize - 1) / BlockSize; + + if (!Len) { + /* send one empty packet */ + gDmaDescIn->status.b.bs = 0x3; + gDmaDescIn->status.b.l = 1; + gDmaDescIn->status.b.ioc = 1; + gDmaDescIn->status.b.sp = 1; + gDmaDescIn->status.b.bytes = 0; + gDmaDescIn->buf = 0; + gDmaDescIn->status.b.sts = 0; + gDmaDescIn->status.b.bs = 0x0; + + WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn)); // DMA Address (DMAAddr) is zero + } else { + WRITE_REG32 (DIEPTSIZ (Ep), Len | (Packets << 19)); + + //flush cache + WriteBackDataCacheRange ((VOID *)Ptr, Len); + + gDmaDescIn->status.b.bs = 0x3; + gDmaDescIn->status.b.l = 1; + gDmaDescIn->status.b.ioc = 1; + gDmaDescIn->status.b.sp = 1; + gDmaDescIn->status.b.bytes = Len; + gDmaDescIn->buf = (UINT32)((UINTN)Ptr); + gDmaDescIn->status.b.sts = 0; + gDmaDescIn->status.b.bs = 0x0; + WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn)); // Ptr is DMA address + } + ArmDataSynchronizationBarrier (); + /* epena & cnak */ + WRITE_REG32 (DIEPCTL (Ep), READ_REG32 (DIEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11); +} + +STATIC +VOID +EpRx ( + IN UINTN Ep, + IN UINTN Len + ) +{ + /* EPx UNSTALL */ + WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & (~DXEPCTL_STALL))); + /* EPx OUT ACTIVE */ + WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_USBACTEP)); + + if (Len >= DATA_SIZE) { + RxDescBytes = DATA_SIZE; + } else { + RxDescBytes = Len; + } + + RxBuf = AllocatePool (DATA_SIZE); + ASSERT (RxBuf != NULL); + + InvalidateDataCacheRange (RxBuf, Len); + + gDmaDesc->status.b.bs = 0x3; + gDmaDesc->status.b.mtrf = 0; + gDmaDesc->status.b.sr = 0; + gDmaDesc->status.b.l = 1; + gDmaDesc->status.b.ioc = 1; + gDmaDesc->status.b.sp = 0; + gDmaDesc->status.b.bytes = (UINT32)RxDescBytes; + gDmaDesc->buf = (UINT32)((UINTN)RxBuf); + gDmaDesc->status.b.sts = 0; + gDmaDesc->status.b.bs = 0x0; + + ArmDataSynchronizationBarrier (); + WRITE_REG32 (DOEPDMA (Ep), (UINT32)((UINTN)gDmaDesc)); + /* EPx OUT ENABLE CLEARNAK */ + WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK)); +} + +STATIC +EFI_STATUS +HandleGetDescriptor ( + IN USB_DEVICE_REQUEST *Request + ) +{ + UINT8 DescriptorType; + UINTN ResponseSize; + VOID *ResponseData; + EFI_USB_STRING_DESCRIPTOR *Descriptor = NULL; + UINTN DescriptorSize; + + ResponseSize = 0; + ResponseData = NULL; + + // Pretty confused if bmRequestType is anything but this: + ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE); + + // Choose the response + DescriptorType = Request->Value >> 8; + switch (DescriptorType) { + case USB_DESC_TYPE_DEVICE: + DEBUG ((DEBUG_INFO, "USB: Got a request for device descriptor\n")); + ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR); + ResponseData = mDeviceDescriptor; + break; + case USB_DESC_TYPE_CONFIG: + DEBUG ((DEBUG_INFO, "USB: Got a request for config descriptor\n")); + ResponseSize = mConfigDescriptor->TotalLength; + ResponseData = mDescriptors; + break; + case USB_DESC_TYPE_STRING: + DEBUG ((DEBUG_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF)); + switch (Request->Value & 0xff) { + case 0: + DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) + + LANG_LENGTH * sizeof (CHAR16) + 1; + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize); + ASSERT (Descriptor != NULL); + Descriptor->Length = LANG_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetLang (Descriptor->String, &Descriptor->Length); + ResponseSize = Descriptor->Length; + ResponseData = Descriptor; + break; + case 1: + DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) + + MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16) + 1; + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize); + ASSERT (Descriptor != NULL); + Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length); + ResponseSize = Descriptor->Length; + ResponseData = Descriptor; + break; + case 2: + DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) + + PRODUCT_STRING_LENGTH * sizeof (CHAR16) + 1; + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize); + ASSERT (Descriptor != NULL); + Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetProduct (Descriptor->String, &Descriptor->Length); + ResponseSize = Descriptor->Length; + ResponseData = Descriptor; + break; + case 3: + DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) + + SERIAL_STRING_LENGTH * sizeof (CHAR16) + 1; + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize); + ASSERT (Descriptor != NULL); + Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length); + ResponseSize = Descriptor->Length; + ResponseData = Descriptor; + break; + } + break; + default: + DEBUG ((DEBUG_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value)); + break; + } + + // Send the response + if (ResponseData) { + ASSERT (ResponseSize != 0); + + if (Request->Length < ResponseSize) { + // Truncate response + ResponseSize = Request->Length; + } else if (Request->Length > ResponseSize) { + DEBUG ((DEBUG_INFO, "USB: Info: ResponseSize < wLength\n")); + } + + EpTx (0, ResponseData, ResponseSize); + } + if (Descriptor) { + FreePool (Descriptor); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +HandleSetAddress ( + IN USB_DEVICE_REQUEST *Request + ) +{ + // Pretty confused if bmRequestType is anything but this: + ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE); + DEBUG ((DEBUG_INFO, "USB: Setting address to %d\n", Request->Value)); + ResetEndpoints (); + + WRITE_REG32 (DCFG, (READ_REG32 (DCFG) & ~DCFG_DEVADDR_MASK) | DCFG_DEVADDR(Request->Value)); + EpTx (0, 0, 0); + + return EFI_SUCCESS; +} + +STATIC +UINTN +UsbDrvRequestEndpoint ( + IN UINTN Type, + IN UINTN Dir + ) +{ + UINTN Ep = 1; + UINTN Ret, NewBits; + + Ret = Ep | Dir; + NewBits = (Type << 18) | 0x10000000; + + /* + * (Type << 18):Endpoint Type (EPType) + * 0x10000000:Endpoint Enable (EPEna) + * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control. + * (ep<<22):TxFIFO Number (TxFNum) + * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint. + */ + if (Dir) { // IN: to host + WRITE_REG32 (DIEPCTL (Ep), ((READ_REG32 (DIEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits | (Ep << 22) | DXEPCTL_NAKSTS); + } else { // OUT: to device + WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits); + } + + return Ret; +} + +STATIC +EFI_STATUS +HandleSetConfiguration ( + IN USB_DEVICE_REQUEST *Request + ) +{ + ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE); + + // Cancel all transfers + ResetEndpoints (); + + UsbDrvRequestEndpoint (2, 0); + UsbDrvRequestEndpoint (2, 0x80); + + WRITE_REG32 (DIEPCTL1, (READ_REG32 (DIEPCTL1)) | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11); + + /* Enable interrupts on all endpoints */ + WRITE_REG32 (DAINTMSK, ~0); + + EpRx (1, CMD_SIZE); + EpTx (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 = HandleGetDescriptor (Request); + break; + case USB_DEV_SET_ADDRESS: + Status = HandleSetAddress (Request); + break; + case USB_DEV_SET_CONFIGURATION: + Status = HandleSetConfiguration (Request); + break; + default: + DEBUG ((DEBUG_ERROR, + "Didn't understand RequestType 0x%x Request 0x%x\n", + Request->RequestType, Request->Request)); + Status = EFI_INVALID_PARAMETER; + break; + } + + return Status; +} + + +// Instead of actually registering interrupt handlers, we poll the controller's +// interrupt source register in this function. +STATIC +VOID +CheckInterrupts ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 Ints, EpInts; + + + // interrupt register + Ints = READ_REG32 (GINTSTS); + + /* + * bus reset + * The core sets this bit to indicate that a reset is detected on the USB. + */ + if (Ints & GINTSTS_USBRST) { + WRITE_REG32 (DCFG, DCFG_DESCDMA | DCFG_NZ_STS_OUT_HSHK); + ResetEndpoints (); + } + + /* + * enumeration done, we now know the speed + * The core sets this bit to indicate that speed enumeration is complete. The + * application must read the Device Status (DSTS) register to obtain the + * enumerated speed. + */ + if (Ints & GINTSTS_ENUMDONE) { + /* Set up the maximum packet sizes accordingly */ + UINTN MaxPacket = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64; + //Set Maximum In Packet Size (MPS) + WRITE_REG32 (DIEPCTL1, ((READ_REG32 (DIEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket); + //Set Maximum Out Packet Size (MPS) + WRITE_REG32 (DOEPCTL1, ((READ_REG32 (DOEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket); + } + + /* + * IN EP event + * The core sets this bit to indicate that an interrupt is pending on one of the IN + * endpoInts of the core (in Device mode). The application must read the + * Device All EndpoInts Interrupt (DAINT) register to determine the exact + * number of the IN endpoint on which the interrupt occurred, and then read + * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to + * determine the exact cause of the interrupt. The application must clear the + * appropriate status bit in the corresponding DIEPINTn register to clear this bit. + */ + if (Ints & GINTSTS_IEPINT) { + EpInts = READ_REG32 (DIEPINT0); + WRITE_REG32 (DIEPINT0, EpInts); + if (EpInts & DXEPINT_XFERCOMPL) { + DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0))); + } + + EpInts = READ_REG32 (DIEPINT1); + WRITE_REG32 (DIEPINT1, EpInts); + if (EpInts & DXEPINT_XFERCOMPL) { + DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n")); + } + } + + /* + * OUT EP event + * The core sets this bit to indicate that an interrupt is pending on one of the + * OUT endpoints of the core (in Device mode). The application must read the + * Device All EndpoInts Interrupt (DAINT) register to determine the exact + * number of the OUT endpoint on which the interrupt occurred, and then read + * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register + * to determine the exact cause of the interrupt. The application must clear the + * appropriate status bit in the corresponding DOEPINTn register to clear this bit. + */ + if (Ints & GINTSTS_OEPINT) { + /* indicates the status of an endpoint + * with respect to USB- and AHB-related events. */ + EpInts = READ_REG32 (DOEPINT0); + if (EpInts) { + WRITE_REG32 (DOEPINT0, EpInts); + if (EpInts & DXEPINT_XFERCOMPL) { + DEBUG ((DEBUG_INFO, "INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32 (DOEPTSIZ0))); + } + /* + * + IN Token Received When TxFIFO is Empty (INTknTXFEmp) + * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic) + * was empty. This interrupt is asserted on the endpoint for which the IN token + * was received. + */ + if (EpInts & BIT3) { /* SETUP phase done */ + WRITE_REG32 (DIEPCTL0, READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK); + WRITE_REG32 (DOEPCTL0, READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK); + /*clear IN EP intr*/ + WRITE_REG32 (DIEPINT0, ~0); + HandleDeviceRequest((USB_DEVICE_REQUEST *)gCtrlReq); + } + + /* Make sure EP0 OUT is set up to accept the next request */ + WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64)); + /* + * IN Token Received When TxFIFO is Empty (INTknTXFEmp) + * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic) + * was empty. This interrupt is asserted on the endpoint for which the IN token + * was received. + */ + gDmaDescEp0->status.b.bs = 0x3; + gDmaDescEp0->status.b.mtrf = 0; + gDmaDescEp0->status.b.sr = 0; + gDmaDescEp0->status.b.l = 1; + gDmaDescEp0->status.b.ioc = 1; + gDmaDescEp0->status.b.sp = 0; + gDmaDescEp0->status.b.bytes = 64; + gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq); + gDmaDescEp0->status.b.sts = 0; + gDmaDescEp0->status.b.bs = 0x0; + WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0)); + // endpoint enable; clear NAK + WRITE_REG32 (DOEPCTL0, DXEPCTL_EPENA | DXEPCTL_CNAK); + } + + EpInts = (READ_REG32 (DOEPINT1)); + if (EpInts) { + WRITE_REG32 (DOEPINT1, EpInts); + /* Transfer Completed Interrupt (XferCompl);Transfer completed */ + if (EpInts & DXEPINT_XFERCOMPL) { + + UINTN Bytes = RxDescBytes - gDmaDesc->status.b.bytes; + UINTN Len = 0; + + ArmDataSynchronizationBarrier (); + if (MATCH_CMD_LITERAL ("download", RxBuf)) { + mNumDataBytes = AsciiStrHexToUint64 (RxBuf + sizeof ("download")); + } else { + if (mNumDataBytes != 0) { + mNumDataBytes -= Bytes; + } + } + + mDataReceivedCallback (Bytes, RxBuf); + + if (mNumDataBytes == 0) { + Len = CMD_SIZE; + } else if (mNumDataBytes > DATA_SIZE) { + Len = DATA_SIZE; + } else { + Len = mNumDataBytes; + } + + EpRx (1, Len); + } + } + } + + //WRITE_REG32 clear ints + WRITE_REG32 (GINTSTS, Ints); +} + +EFI_STATUS +DwUsbSend ( + IN UINT8 EndpointIndex, + IN UINTN Size, + IN CONST VOID *Buffer + ) +{ + EpTx (EndpointIndex, Buffer, Size); + return EFI_SUCCESS; +} + +STATIC +VOID +DwUsbInit ( + VOID + ) +{ + VOID *Buf; + UINT32 Data; + + Buf = UncachedAllocatePages (16); + gDmaDesc = Buf; + gDmaDescEp0 = gDmaDesc + sizeof (dwc_otg_dev_dma_desc_t); + gDmaDescIn = gDmaDescEp0 + sizeof (dwc_otg_dev_dma_desc_t); + gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (dwc_otg_dev_dma_desc_t); + + ZeroMem (gDmaDesc, sizeof (dwc_otg_dev_dma_desc_t)); + ZeroMem (gDmaDescEp0, sizeof (dwc_otg_dev_dma_desc_t)); + ZeroMem (gDmaDescIn, sizeof (dwc_otg_dev_dma_desc_t)); + + /*Reset usb controller.*/ + /* Wait for OTG AHB master idle */ + do { + Data = READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE; + } while (Data == 0); + + /* OTG: Assert Software Reset */ + WRITE_REG32 (GRSTCTL, GRSTCTL_CSFTRST); + + /* Wait for OTG to ack reset */ + while (READ_REG32 (GRSTCTL) & GRSTCTL_CSFTRST); + + /* Wait for OTG AHB master idle */ + while ((READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE) == 0); + + WRITE_REG32 (GDFIFOCFG, DATA_FIFO_CONFIG); + WRITE_REG32 (GRXFSIZ, RX_SIZE); + WRITE_REG32 (GNPTXFSIZ, ENDPOINT_TX_SIZE); + WRITE_REG32 (DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1); + WRITE_REG32 (DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2); + WRITE_REG32 (DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3); + WRITE_REG32 (DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4); + WRITE_REG32 (DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5); + WRITE_REG32 (DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6); + WRITE_REG32 (DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7); + WRITE_REG32 (DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8); + WRITE_REG32 (DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9); + WRITE_REG32 (DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10); + WRITE_REG32 (DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11); + WRITE_REG32 (DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12); + WRITE_REG32 (DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13); + WRITE_REG32 (DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14); + WRITE_REG32 (DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15); + + /* + * set Periodic TxFIFO Empty Level, + * Non-Periodic TxFIFO Empty Level, + * Enable DMA, Unmask Global Intr + */ + WRITE_REG32 (GAHBCFG, GAHBCFG_CTRL_MASK); + + /*select 8bit UTMI+, ULPI Inerface*/ + WRITE_REG32 (GUSBCFG, 0x2400); + + /* Detect usb work mode,host or device? */ + do { + Data = READ_REG32 (GINTSTS); + } while (Data & GINTSTS_CURMODE_HOST); + MicroSecondDelay (3); + + /*Init global and device mode csr register.*/ + /*set Non-Zero-Length status out handshake */ + Data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK; + WRITE_REG32 (DCFG, Data); + + /* Interrupt unmask: IN event, OUT event, bus reset */ + Data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE | GINTSTS_USBRST; + WRITE_REG32 (GINTMSK, Data); + + do { + Data = READ_REG32 (GINTSTS) & GINTSTS_ENUMDONE; + } while (Data); + + /* Clear any pending OTG Interrupts */ + WRITE_REG32 (GOTGINT, ~0); + /* Clear any pending interrupts */ + WRITE_REG32 (GINTSTS, ~0); + WRITE_REG32 (GINTMSK, ~0); + Data = READ_REG32 (GOTGINT); + Data &= ~0x3000; + WRITE_REG32 (GOTGINT, Data); + + /* endpoint settings cfg */ + ResetEndpoints (); + MicroSecondDelay (1); + + /* init finish. and ready to transfer data */ + + /* Soft Disconnect */ + WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE | DCTL_SFTDISCON); + MicroSecondDelay (10000); + + /* Soft Reconnect */ + WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE); +} + +EFI_STATUS +EFIAPI +DwUsbStart ( + IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor, + IN VOID **Descriptors, + IN USB_DEVICE_RX_CALLBACK RxCallback, + IN USB_DEVICE_TX_CALLBACK TxCallback + ) +{ + UINT8 *Ptr; + EFI_STATUS Status; + EFI_EVENT TimerEvent; + + ASSERT (DeviceDescriptor != NULL); + ASSERT (Descriptors[0] != NULL); + ASSERT (RxCallback != NULL); + ASSERT (TxCallback != NULL); + + DwUsbInit(); + + mDeviceDescriptor = DeviceDescriptor; + mDescriptors = Descriptors[0]; + + // Right now we just support one configuration + ASSERT (mDeviceDescriptor->NumConfigurations == 1); + mDeviceDescriptor->StrManufacturer = 1; + mDeviceDescriptor->StrProduct = 2; + mDeviceDescriptor->StrSerialNumber = 3; + // ... and one interface + mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors; + ASSERT (mConfigDescriptor->NumInterfaces == 1); + + Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR); + mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr; + Ptr += sizeof (USB_INTERFACE_DESCRIPTOR); + + mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr; + + mDataReceivedCallback = RxCallback; + mDataSentCallback = TxCallback; + + // Register a timer event so CheckInterupts gets called periodically + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + CheckInterrupts, + NULL, + &TimerEvent + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->SetTimer ( + TimerEvent, + TimerPeriodic, + DW_INTERRUPT_POLL_PERIOD + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +USB_DEVICE_PROTOCOL mUsbDevice = { + DwUsbStart, + DwUsbSend +}; + + +EFI_STATUS +EFIAPI +DwUsbEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = DwUsb->PhyInit(USB_DEVICE_MODE); + if (EFI_ERROR (Status)) { + return Status; + } + + return gBS->InstallProtocolInterface ( + &ImageHandle, + &gUsbDeviceProtocolGuid, + EFI_NATIVE_INTERFACE, + &mUsbDevice + ); +} diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec new file mode 100644 index 0000000..f991492 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec @@ -0,0 +1,46 @@ +#/** @file +# Framework Module Development Environment Industry Standards +# +# This Package provides headers and libraries that conform to EFI/PI Industry standards. +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR> +# Copyright (c) 2015-2017, Linaro. All rights reserved.<BR> +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + DEC_SPECIFICATION = 0x00010019 + PACKAGE_NAME = OpenPlatformDriversUsbDwUsbDxePkg + PACKAGE_GUID = 114a3be9-10f7-4bf1-81ca-09ac52d4c3d5 + PACKAGE_VERSION = 0.1 + + +################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################ + +[Guids.common] + gAndroidFastbootUsbGuid = { 0xf6bec3fe, 0x88fb, 0x11e3, { 0xae, 0x84, 0xe7, 0x3b, 0x77, 0x56, 0x1c, 0x35 }} + gDwUsbDxeTokenSpaceGuid = { 0x131c4d02, 0x9449, 0x4ee9, { 0xba, 0x3d, 0x69, 0x50, 0x21, 0x89, 0x26, 0x0b }} + +[Protocols.common] + gDwUsbProtocolGuid = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }} + +[PcdsFixedAtBuild.common] + # DwUsb Driver PCDs + gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0x0|UINT32|0x00000001 + gDwUsbDxeTokenSpaceGuid.PcdSysCtrlBaseAddress|0x0|UINT32|0x00000002 diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.h b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h new file mode 100644 index 0000000..7f909c3 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h @@ -0,0 +1,627 @@ +/** @file + + Copyright (c) 2015-2017, Linaro. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DW_USB_DXE_H__ +#define __DW_USB_DXE_H__ + +#define DW_USB_BASE FixedPcdGet32 (PcdDwUsbDxeBaseAddress) + +#define READ_REG32(Offset) MmioRead32 (DW_USB_BASE + Offset) +#define READ_REG16(Offset) (UINT16)READ_REG32 (Offset) +#define WRITE_REG32(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, Val) +#define WRITE_REG16(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val) +#define WRITE_REG8(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val) + +// Max packet size in bytes (For Full Speed USB 64 is the only valid value) +#define MAX_PACKET_SIZE_CONTROL 64 + +#define MAX_PACKET_SIZE_BULK 512 + +// 8 Endpoints, in and out. Don't count the Endpoint 0 setup buffer +#define DW_NUM_ENDPOINTS 16 + +// Endpoint Indexes +#define DW_EP0SETUP 0x20 +#define DW_EP0RX 0x00 +#define DW_EP0TX 0x01 +#define DW_EP1RX 0x02 +#define DW_EP1TX 0x03 + +// DcInterrupt bits +#define DW_DC_INTERRUPT_EP1TX BIT13 +#define DW_DC_INTERRUPT_EP1RX BIT12 +#define DW_DC_INTERRUPT_EP0TX BIT11 +#define DW_DC_INTERRUPT_EP0RX BIT10 +#define DW_DC_INTERRUPT_EP0SETUP BIT8 +#define DW_DC_INTERRUPT_VBUS BIT7 +#define DW_DC_INTERRUPT_DMA BIT6 +#define DW_DC_INTERRUPT_HS_STAT BIT5 +#define DW_DC_INTERRUPT_RESUME BIT4 +#define DW_DC_INTERRUPT_SUSP BIT3 +#define DW_DC_INTERRUPT_PSOF BIT2 +#define DW_DC_INTERRUPT_SOF BIT1 +#define DW_DC_INTERRUPT_BRESET BIT0 +// All valid peripheral controller int rrupts +#define DW_DC_INTERRUPT_MASK 0x003FFFDFF + +#define DW_ADDRESS 0x200 +#define DW_ADDRESS_DEVEN BIT7 + +#define DW_MODE 0x20C +#define DW_MODE_DATA_BUS_WIDTH BIT8 +#define DW_MODE_CLKAON BIT7 +#define DW_MODE_SFRESET BIT4 +#define DW_MODE_WKUPCS BIT2 + +#define DW_ENDPOINT_MAX_PACKET_SIZE 0x204 + +#define DW_ENDPOINT_TYPE 0x208 +#define DW_ENDPOINT_TYPE_NOEMPKT BIT4 +#define DW_ENDPOINT_TYPE_ENABLE BIT3 + +#define DW_INTERRUPT_CONFIG 0x210 +// Interrupt config value to only interrupt on ACK of IN and OUT tokens +#define DW_INTERRUPT_CONFIG_ACK_ONLY (BIT2 | BIT5 | BIT6) + +#define DW_DC_INTERRUPT 0x218 +#define DW_DC_INTERRUPT_ENABLE 0x214 + +#define DW_CTRL_FUNCTION 0x228 +#define DW_CTRL_FUNCTION_VENDP BIT3 +#define DW_CTRL_FUNCTION_DSEN BIT2 +#define DW_CTRL_FUNCTION_STATUS BIT1 + +#define DW_DEVICE_UNLOCK 0x27C +#define DW_DEVICE_UNLOCK_MAGIC 0xAA37 + +#define DW_SW_RESET_REG 0x30C +#define DW_SW_RESET_ALL BIT0 + +#define DW_DEVICE_ID 0x370 + +#define DW_OTG_CTRL_SET 0x374 +#define DW_OTG_CTRL_CLR (OTG_CTRL_SET + 2) +#define DW_OTG_CTRL_OTG_DISABLE BIT10 +#define DW_OTG_CTRL_VBUS_CHRG BIT6 +#define DW_OTG_CTRL_VBUS_DISCHRG BIT5 +#define DW_OTG_CTRL_DM_PULLDOWN BIT2 +#define DW_OTG_CTRL_DP_PULLDOWN BIT1 +#define DW_OTG_CTRL_DP_PULLUP BIT0 + +#define DW_OTG_STATUS 0x378 +#define DW_OTG_STATUS_B_SESS_END BIT7 +#define DW_OTG_STATUS_A_B_SESS_VLD BIT1 + +#define DW_OTG_INTERRUPT_LATCH_SET 0x37C +#define DW_OTG_INTERRUPT_LATCH_CLR 0x37E +#define DW_OTG_INTERRUPT_ENABLE_RISE 0x384 + +#define DW_DMA_ENDPOINT_INDEX 0x258 + +#define DW_ENDPOINT_INDEX 0x22c +#define DW_DATA_PORT 0x220 +#define DW_BUFFER_LENGTH 0x21c + +// Device ID Values +#define PHILLIPS_VENDOR_ID_VAL 0x04cc +#define DW_PRODUCT_ID_VAL 0x1761 +#define DW_DEVICE_ID_VAL ((ISP1761_PRODUCT_ID_VAL << 16) | \ + PHILLIPS_VENDOR_ID_VAL) + +#define DWC_OTG_BASE DW_USB_BASE + +#define USB_NUM_ENDPOINTS 2 +#define MAX_EPS_CHANNELS 16 + +#define BULK_OUT_EP 1 +#define BULK_IN_EP 1 + +#define RX_REQ_LEN 512 +#define MAX_PACKET_LEN 512 + +#define DATA_FIFO_CONFIG 0x0F801000 +/* RX FIFO: 2048 bytes */ +#define RX_SIZE 0x00000200 +/* Non-periodic TX FIFO: 128 bytes. start address: 0x200 * 4. */ +#define ENDPOINT_TX_SIZE 0x01000200 + +/* EP1 TX FIFO: 1024 bytes. start address: 0x220 * 4. */ +/* EP2 TX FIFO: 1024 bytes. start address: 0x320 * 4. */ +/* EP3 TX FIFO: 1024 bytes. start address: 0x420 * 4. */ +/* EP4 TX FIFO: 1024 bytes. start address: 0x520 * 4. */ +/* EP5 TX FIFO: 128 bytes. start address: 0x620 * 4. */ +/* EP6 TX FIFO: 128 bytes. start address: 0x640 * 4. */ +/* EP7 TX FIFO: 128 bytes. start address: 0x660 * 4. */ +/* EP8 TX FIFO: 128 bytes. start address: 0x680 * 4. */ +/* EP9 TX FIFO: 128 bytes. start address: 0x6A0 * 4. */ +/* EP10 TX FIFO: 128 bytes. start address: 0x6C0 * 4. */ +/* EP11 TX FIFO: 128 bytes. start address: 0x6E0 * 4. */ +/* EP12 TX FIFO: 128 bytes. start address: 0x700 * 4. */ +/* EP13 TX FIFO: 128 bytes. start address: 0x720 * 4. */ +/* EP14 TX FIFO: 128 bytes. start address: 0x740 * 4. */ +/* EP15 TX FIFO: 128 bytes. start address: 0x760 * 4. */ + +#define DATA_IN_ENDPOINT_TX_FIFO1 0x01000220 +#define DATA_IN_ENDPOINT_TX_FIFO2 0x01000320 +#define DATA_IN_ENDPOINT_TX_FIFO3 0x01000420 +#define DATA_IN_ENDPOINT_TX_FIFO4 0x01000520 +#define DATA_IN_ENDPOINT_TX_FIFO5 0x00200620 +#define DATA_IN_ENDPOINT_TX_FIFO6 0x00200640 +#define DATA_IN_ENDPOINT_TX_FIFO7 0x00200680 +#define DATA_IN_ENDPOINT_TX_FIFO8 0x002006A0 +#define DATA_IN_ENDPOINT_TX_FIFO9 0x002006C0 +#define DATA_IN_ENDPOINT_TX_FIFO10 0x002006E0 +#define DATA_IN_ENDPOINT_TX_FIFO11 0x00200700 +#define DATA_IN_ENDPOINT_TX_FIFO12 0x00200720 +#define DATA_IN_ENDPOINT_TX_FIFO13 0x00200740 +#define DATA_IN_ENDPOINT_TX_FIFO14 0x00200760 +#define DATA_IN_ENDPOINT_TX_FIFO15 0x00200F00 + +/*DWC_OTG regsiter descriptor*/ +/*Device mode CSR MAP*/ +#define DEVICE_CSR_BASE 0x800 +/*Device mode CSR MAP*/ +#define DEVICE_INEP_BASE 0x900 +/*Device mode CSR MAP*/ +#define DEVICE_OUTEP_BASE 0xB00 + +/*** OTG LINK CORE REGISTERS ***/ +/* Core Global Registers */ +#define GOTGCTL 0x000 +#define GOTGINT 0x004 +#define GAHBCFG 0x008 +#define GAHBCFG_P_TXF_EMP_LVL (1 << 8) +#define GAHBCFG_NP_TXF_EMP_LVL (1 << 7) +#define GAHBCFG_DMA_EN (1 << 5) +#define GAHBCFG_GLBL_INTR_EN (1 << 0) +#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \ + GAHBCFG_NP_TXF_EMP_LVL | \ + GAHBCFG_DMA_EN | \ + GAHBCFG_GLBL_INTR_EN) + +#define GUSBCFG 0x00C +#define GRSTCTL 0x010 +#define GRSTCTL_AHBIDLE (1 << 31) +#define GRSTCTL_CSFTRST (1 << 0) + +#define GINTSTS 0x014 +#define GINTSTS_WKUPINT BIT31 +#define GINTSTS_SESSREGINT BIT30 +#define GINTSTS_DISCONNINT BIT29 +#define GINTSTS_CONIDSTSCHNG BIT28 +#define GINTSTS_LPMTRANRCVD BIT27 +#define GINTSTS_PTXFEMP BIT26 +#define GINTSTS_HCHINT BIT25 +#define GINTSTS_PRTINT BIT24 +#define GINTSTS_RESETDET BIT23 +#define GINTSTS_FET_SUSP BIT22 +#define GINTSTS_INCOMPL_IP BIT21 +#define GINTSTS_INCOMPL_SOIN BIT20 +#define GINTSTS_OEPINT BIT19 +#define GINTSTS_IEPINT BIT18 +#define GINTSTS_EPMIS BIT17 +#define GINTSTS_RESTOREDONE BIT16 +#define GINTSTS_EOPF BIT15 +#define GINTSTS_ISOUTDROP BIT14 +#define GINTSTS_ENUMDONE BIT13 +#define GINTSTS_USBRST BIT12 +#define GINTSTS_USBSUSP BIT11 +#define GINTSTS_ERLYSUSP BIT10 +#define GINTSTS_I2CINT BIT9 +#define GINTSTS_ULPI_CK_INT BIT8 +#define GINTSTS_GOUTNAKEFF BIT7 +#define GINTSTS_GINNAKEFF BIT6 +#define GINTSTS_NPTXFEMP BIT5 +#define GINTSTS_RXFLVL BIT4 +#define GINTSTS_SOF BIT3 +#define GINTSTS_OTGINT BIT2 +#define GINTSTS_MODEMIS BIT1 +#define GINTSTS_CURMODE_HOST BIT0 + +#define GINTMSK 0x018 +#define GRXSTSR 0x01C +#define GRXSTSP 0x020 +#define GRXFSIZ 0x024 +#define GNPTXFSIZ 0x028 +#define GNPTXSTS 0x02C + +#define GHWCFG1 0x044 +#define GHWCFG2 0x048 +#define GHWCFG3 0x04c +#define GHWCFG4 0x050 +#define GLPMCFG 0x054 + +#define GDFIFOCFG 0x05c + +#define HPTXFSIZ 0x100 +#define DIEPTXF(x) (0x100 + 4 * (x)) +#define DIEPTXF1 0x104 +#define DIEPTXF2 0x108 +#define DIEPTXF3 0x10C +#define DIEPTXF4 0x110 +#define DIEPTXF5 0x114 +#define DIEPTXF6 0x118 +#define DIEPTXF7 0x11C +#define DIEPTXF8 0x120 +#define DIEPTXF9 0x124 +#define DIEPTXF10 0x128 +#define DIEPTXF11 0x12C +#define DIEPTXF12 0x130 +#define DIEPTXF13 0x134 +#define DIEPTXF14 0x138 +#define DIEPTXF15 0x13C + +/*** HOST MODE REGISTERS ***/ +/* Host Global Registers */ +#define HCFG 0x400 +#define HFIR 0x404 +#define HFNUM 0x408 +#define HPTXSTS 0x410 +#define HAINT 0x414 +#define HAINTMSK 0x418 + +/* Host Port Control and Status Registers */ +#define HPRT 0x440 + +/* Host Channel-Specific Registers */ +#define HCCHAR(x) (0x500 + 0x20 * (x)) +#define HCSPLT(x) (0x504 + 0x20 * (x)) +#define HCINT(x) (0x508 + 0x20 * (x)) +#define HCINTMSK(x) (0x50C + 0x20 * (x)) +#define HCTSIZ(x) (0x510 + 0x20 * (x)) +#define HCDMA(x) (0x514 + 0x20 * (x)) +#define HCCHAR0 0x500 +#define HCSPLT0 0x504 +#define HCINT0 0x508 +#define HCINTMSK0 0x50C +#define HCTSIZ0 0x510 +#define HCDMA0 0x514 +#define HCCHAR1 0x520 +#define HCSPLT1 0x524 +#define HCINT1 0x528 +#define HCINTMSK1 0x52C +#define HCTSIZ1 0x530 +#define HCDMA1 0x534 +#define HCCHAR2 0x540 +#define HCSPLT2 0x544 +#define HCINT2 0x548 +#define HCINTMSK2 0x54C +#define HCTSIZ2 0x550 +#define HCDMA2 0x554 +#define HCCHAR3 0x560 +#define HCSPLT3 0x564 +#define HCINT3 0x568 +#define HCINTMSK3 0x56C +#define HCTSIZ3 0x570 +#define HCDMA3 0x574 +#define HCCHAR4 0x580 +#define HCSPLT4 0x584 +#define HCINT4 0x588 +#define HCINTMSK4 0x58C +#define HCTSIZ4 0x590 +#define HCDMA4 0x594 +#define HCCHAR5 0x5A0 +#define HCSPLT5 0x5A4 +#define HCINT5 0x5A8 +#define HCINTMSK5 0x5AC +#define HCTSIZ5 0x5B0 +#define HCDMA5 0x5B4 +#define HCCHAR6 0x5C0 +#define HCSPLT6 0x5C4 +#define HCINT6 0x5C8 +#define HCINTMSK6 0x5CC +#define HCTSIZ6 0x5D0 +#define HCDMA6 0x5D4 +#define HCCHAR7 0x5E0 +#define HCSPLT7 0x5E4 +#define HCINT7 0x5E8 +#define HCINTMSK7 0x5EC +#define HCTSIZ7 0x5F0 +#define HCDMA7 0x5F4 +#define HCCHAR8 0x600 +#define HCSPLT8 0x604 +#define HCINT8 0x608 +#define HCINTMSK8 0x60C +#define HCTSIZ8 0x610 +#define HCDMA8 0x614 +#define HCCHAR9 0x620 +#define HCSPLT9 0x624 +#define HCINT9 0x628 +#define HCINTMSK9 0x62C +#define HCTSIZ9 0x630 +#define HCDMA9 0x634 +#define HCCHAR10 0x640 +#define HCSPLT10 0x644 +#define HCINT10 0x648 +#define HCINTMSK10 0x64C +#define HCTSIZ10 0x650 +#define HCDMA10 0x654 +#define HCCHAR11 0x660 +#define HCSPLT11 0x664 +#define HCINT11 0x668 +#define HCINTMSK11 0x66C +#define HCTSIZ11 0x670 +#define HCDMA11 0x674 +#define HCCHAR12 0x680 +#define HCSPLT12 0x684 +#define HCINT12 0x688 +#define HCINTMSK12 0x68C +#define HCTSIZ12 0x690 +#define HCDMA12 0x694 +#define HCCHAR13 0x6A0 +#define HCSPLT13 0x6A4 +#define HCINT13 0x6A8 +#define HCINTMSK13 0x6AC +#define HCTSIZ13 0x6B0 +#define HCDMA13 0x6B4 +#define HCCHAR14 0x6C0 +#define HCSPLT14 0x6C4 +#define HCINT14 0x6C8 +#define HCINTMSK14 0x6CC +#define HCTSIZ14 0x6D0 +#define HCDMA14 0x6D4 +#define HCCHAR15 0x6E0 +#define HCSPLT15 0x6E4 +#define HCINT15 0x6E8 +#define HCINTMSK15 0x6EC +#define HCTSIZ15 0x6F0 +#define HCDMA15 0x6F4 + +/*** DEVICE MODE REGISTERS ***/ +/* Device Global Registers */ +#define DCFG 0x800 +#define DCFG_DESCDMA BIT23 +#define DCFG_EPMISCNT_MASK (0x1F << 18) +#define DCFG_EPMISCNT_SHIFT 18 +#define DCFG_DEVADDR_MASK (0x7F << 4) +#define DCFG_DEVADDR_SHIFT 4 +#define DCFG_DEVADDR(x) (((x) << DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK) +#define DCFG_NZ_STS_OUT_HSHK BIT2 + +#define DCTL 0x804 +#define DCTL_PWRONPRGDONE BIT11 +#define DCTL_GNPINNAKSTS BIT2 +#define DCTL_SFTDISCON BIT1 + +#define DSTS 0x808 +#define DIEPMSK 0x810 +#define DOEPMSK 0x814 + +#define DXEPMSK_TIMEOUTMSK BIT3 +#define DXEPMSK_AHBERMSK BIT2 +#define DXEPMSK_XFERCOMPLMSK BIT0 + +#define DAINT 0x818 +#define DAINTMSK 0x81C + +#define DAINTMSK_OUTEPMSK_SHIFT 16 +#define DAINTMSK_INEPMSK_SHIFT 0 + +#define DTKNQR1 0x820 +#define DTKNQR2 0x824 +#define DVBUSDIS 0x828 +#define DVBUSPULSE 0x82C +#define DTHRCTL 0x830 + +/* Device Logical IN Endpoint-Specific Registers */ +#define DIEPCTL(x) (0x900 + 0x20 * (x)) +#define DIEPINT(x) (0x908 + 0x20 * (x)) +#define DIEPTSIZ(x) (0x910 + 0x20 * (x)) +#define DIEPDMA(x) (0x914 + 0x20 * (x)) +#define DTXFSTS(x) (0x918 + 0x20 * (x)) + +#define DIEPCTL0 0x900 +#define DIEPINT0 0x908 +#define DIEPTSIZ0 0x910 +#define DIEPDMA0 0x914 +#define DIEPCTL1 0x920 +#define DIEPINT1 0x928 +#define DIEPTSIZ1 0x930 +#define DIEPDMA1 0x934 +#define DIEPCTL2 0x940 +#define DIEPINT2 0x948 +#define DIEPTSIZ2 0x950 +#define DIEPDMA2 0x954 +#define DIEPCTL3 0x960 +#define DIEPINT3 0x968 +#define DIEPTSIZ3 0x970 +#define DIEPDMA3 0x974 +#define DIEPCTL4 0x980 +#define DIEPINT4 0x988 +#define DIEPTSIZ4 0x990 +#define DIEPDMA4 0x994 +#define DIEPCTL5 0x9A0 +#define DIEPINT5 0x9A8 +#define DIEPTSIZ5 0x9B0 +#define DIEPDMA5 0x9B4 +#define DIEPCTL6 0x9C0 +#define DIEPINT6 0x9C8 +#define DIEPTSIZ6 0x9D0 +#define DIEPDMA6 0x9D4 +#define DIEPCTL7 0x9E0 +#define DIEPINT7 0x9E8 +#define DIEPTSIZ7 0x9F0 +#define DIEPDMA7 0x9F4 +#define DIEPCTL8 0xA00 +#define DIEPINT8 0xA08 +#define DIEPTSIZ8 0xA10 +#define DIEPDMA8 0xA14 +#define DIEPCTL9 0xA20 +#define DIEPINT9 0xA28 +#define DIEPTSIZ9 0xA30 +#define DIEPDMA9 0xA34 +#define DIEPCTL10 0xA40 +#define DIEPINT10 0xA48 +#define DIEPTSIZ10 0xA50 +#define DIEPDMA10 0xA54 +#define DIEPCTL11 0xA60 +#define DIEPINT11 0xA68 +#define DIEPTSIZ11 0xA70 +#define DIEPDMA11 0xA74 +#define DIEPCTL12 0xA80 +#define DIEPINT12 0xA88 +#define DIEPTSIZ12 0xA90 +#define DIEPDMA12 0xA94 +#define DIEPCTL13 0xAA0 +#define DIEPINT13 0xAA8 +#define DIEPTSIZ13 0xAB0 +#define DIEPDMA13 0xAB4 +#define DIEPCTL14 0xAC0 +#define DIEPINT14 0xAC8 +#define DIEPTSIZ14 0xAD0 +#define DIEPDMA14 0xAD4 +#define DIEPCTL15 0xAE0 +#define DIEPINT15 0xAE8 +#define DIEPTSIZ15 0xAF0 +#define DIEPDMA15 0xAF4 + +/* Device Logical OUT Endpoint-Specific Registers */ +#define DOEPCTL(x) (0xB00 + 0x20 * (x)) +#define DOEPINT(x) (0xB08 + 0x20 * (x)) +#define DOEPTSIZ(x) (0xB10 + 0x20 * (x)) + +#define DXEPINT_EPDISBLD BIT1 +#define DXEPINT_XFERCOMPL BIT0 + +#define DXEPTSIZ_SUPCNT(x) (((x) & 0x3) << 29) +#define DXEPTSIZ_PKTCNT(x) (((x) & 0x3) << 19) +#define DXEPTSIZ_XFERSIZE(x) ((x) & 0x7F) + +#define DOEPDMA(x) (0xB14 + 0x20 * (x)) +#define DOEPCTL0 0xB00 +#define DOEPINT0 0xB08 +#define DOEPTSIZ0 0xB10 +#define DOEPDMA0 0xB14 +#define DOEPCTL1 0xB20 +#define DOEPINT1 0xB28 +#define DOEPTSIZ1 0xB30 +#define DOEPDMA1 0xB34 +#define DOEPCTL2 0xB40 +#define DOEPINT2 0xB48 +#define DOEPTSIZ2 0xB50 +#define DOEPDMA2 0xB54 +#define DOEPCTL3 0xB60 +#define DOEPINT3 0xB68 +#define DOEPTSIZ3 0xB70 +#define DOEPDMA3 0xB74 +#define DOEPCTL4 0xB80 +#define DOEPINT4 0xB88 +#define DOEPTSIZ4 0xB90 +#define DOEPDMA4 0xB94 +#define DOEPCTL5 0xBA0 +#define DOEPINT5 0xBA8 +#define DOEPTSIZ5 0xBB0 +#define DOEPDMA5 0xBB4 +#define DOEPCTL6 0xBC0 +#define DOEPINT6 0xBC8 +#define DOEPTSIZ6 0xBD0 +#define DOEPDMA6 0xBD4 +#define DOEPCTL7 0xBE0 +#define DOEPINT7 0xBE8 +#define DOEPTSIZ7 0xBF0 +#define DOEPDMA7 0xBF4 +#define DOEPCTL8 0xC00 +#define DOEPINT8 0xC08 +#define DOEPTSIZ8 0xC10 +#define DOEPDMA8 0xC14 +#define DOEPCTL9 0xC20 +#define DOEPINT9 0xC28 +#define DOEPTSIZ9 0xC30 +#define DOEPDMA9 0xC34 +#define DOEPCTL10 0xC40 +#define DOEPINT10 0xC48 +#define DOEPTSIZ10 0xC50 +#define DOEPDMA10 0xC54 +#define DOEPCTL11 0xC60 +#define DOEPINT11 0xC68 +#define DOEPTSIZ11 0xC70 +#define DOEPDMA11 0xC74 +#define DOEPCTL12 0xC80 +#define DOEPINT12 0xC88 +#define DOEPTSIZ12 0xC90 +#define DOEPDMA12 0xC94 +#define DOEPCTL13 0xCA0 +#define DOEPINT13 0xCA8 +#define DOEPTSIZ13 0xCB0 +#define DOEPDMA13 0xCB4 +#define DOEPCTL14 0xCC0 +#define DOEPINT14 0xCC8 +#define DOEPTSIZ14 0xCD0 +#define DOEPDMA14 0xCD4 +#define DOEPCTL15 0xCE0 +#define DOEPINT15 0xCE8 +#define DOEPTSIZ15 0xCF0 +#define DOEPDMA15 0xCF4 + +#define DXEPCTL_EPENA BIT31 +#define DXEPCTL_SNAK BIT27 +#define DXEPCTL_CNAK BIT26 +#define DXEPCTL_STALL BIT21 +#define DXEPCTL_EPTYPE_MASK (BIT19 | BIT18) +#define DXEPCTL_NAKSTS BIT17 +#define DXEPCTL_USBACTEP BIT15 +#define DXEPCTL_MPS_MASK 0x7FF + +/* Power and Clock Gating Register */ +#define PCGCCTL 0xE00 + +#define EP0FIFO 0x1000 + +/** + * This union represents the bit fields in the DMA Descriptor + * status quadlet. Read the quadlet into the <i>d32</i> member then + * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and + * <i>b_iso_in</i> elements. + */ +typedef union { + /** raw register data */ + UINT32 d32; + /** quadlet bits */ + struct { + /** Received number of bytes */ + unsigned bytes:16; + /** NAK bit - only for OUT EPs */ + unsigned nak:1; + unsigned reserved17_22:6; + /** Multiple Transfer - only for OUT EPs */ + unsigned mtrf:1; + /** Setup Packet received - only for OUT EPs */ + unsigned sr:1; + /** Interrupt On Complete */ + unsigned ioc:1; + /** Short Packet */ + unsigned sp:1; + /** Last */ + unsigned l:1; + /** Receive Status */ + unsigned sts:2; + /** Buffer Status */ + unsigned bs:2; + } b; +} dev_dma_desc_sts_t; + +/** + * DMA Descriptor structure + * + * DMA Descriptor structure contains two quadlets: + * Status quadlet and Data buffer pointer. + */ +typedef struct { + /** DMA Descriptor status quadlet */ + dev_dma_desc_sts_t status; + /** DMA Descriptor data buffer pointer */ + UINT32 buf; +} dwc_otg_dev_dma_desc_t; + +#endif //ifndef __DW_USB_DXE_H__ diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf new file mode 100644 index 0000000..fc1e988 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf @@ -0,0 +1,52 @@ +#/** @file +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = DwUsbDxe + FILE_GUID = 72d78ea6-4dee-11e3-8100-f3842a48d0a0 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DwUsbEntryPoint + +[Sources.common] + DwUsbDxe.c + +[LibraryClasses] + ArmLib + DebugLib + IoLib + MemoryAllocationLib + TimerLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UncachedMemoryAllocationLib + CacheMaintenanceLib + +[Protocols] + gEfiDriverBindingProtocolGuid + gUsbDeviceProtocolGuid + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec + +[Pcd] + gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress + +[Depex] + BEFORE gAndroidFastbootUsbGuid diff --git a/Include/Protocol/DwUsb.h b/Include/Protocol/DwUsb.h new file mode 100644 index 0000000..040e126 --- /dev/null +++ b/Include/Protocol/DwUsb.h @@ -0,0 +1,81 @@ +/** @file + + Copyright (c) 2015-2017, Linaro. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DW_USB_H__ +#define __DW_USB_H__ + +// +// Protocol GUID +// +#define DW_USB_PROTOCOL_GUID { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }} + +// +// Protocol interface structure +// +typedef struct _DW_USB_PROTOCOL DW_USB_PROTOCOL; + +#define USB_HOST_MODE 0 +#define USB_DEVICE_MODE 1 +#define USB_CABLE_NOT_ATTACHED 2 + +#define LANG_LENGTH 8 +#define MANU_FACTURER_STRING_LENGTH 32 +#define PRODUCT_STRING_LENGTH 32 +#define SERIAL_STRING_LENGTH 17 + +typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_LANG) ( + OUT CHAR16 *Lang, + OUT UINT8 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_MANU_FACTURER) ( + OUT CHAR16 *ManuFacturer, + OUT UINT8 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_PRODUCT) ( + OUT CHAR16 *Product, + OUT UINT8 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_SERIAL_NO) ( + OUT CHAR16 *SerialNo, + OUT UINT8 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *DW_USB_PHY_INIT) ( + IN UINT8 Mode + ); + +struct _DW_USB_PROTOCOL { + DW_USB_GET_LANG GetLang; + DW_USB_GET_MANU_FACTURER GetManuFacturer; + DW_USB_GET_PRODUCT GetProduct; + DW_USB_GET_SERIAL_NO GetSerialNo; + DW_USB_PHY_INIT PhyInit; +}; + +extern EFI_GUID gDwUsbProtocolGuid; + +#endif
On Sat, Feb 04, 2017 at 01:13:48PM +0800, Haojian Zhuang wrote:
Support Designware USB controller.
A bit more detailed commit message please - which USB controller, which USB standards does it support?
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org
Drivers/Usb/DwUsbDxe/DwUsbDxe.c | 796 ++++++++++++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.dec | 46 +++ Drivers/Usb/DwUsbDxe/DwUsbDxe.h | 627 ++++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.inf | 52 +++ Include/Protocol/DwUsb.h | 81 ++++ 5 files changed, 1602 insertions(+) create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.c create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.dec create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.h create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.inf create mode 100644 Include/Protocol/DwUsb.h
diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.c b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c new file mode 100644 index 0000000..bdd8405 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c @@ -0,0 +1,796 @@ +/** @file
- Copyright (c) 2015-2017, Linaro. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <IndustryStandard/Usb.h> +#include <Library/ArmLib.h> +#include <Library/TimerLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UncachedMemoryAllocationLib.h> +#include <Library/CacheMaintenanceLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/BaseLib.h> +#include <Protocol/DwUsb.h> +#include <Protocol/UsbDevice.h>
Please sort include files alphabetically.
+#include "DwUsbDxe.h"
+#define USB_TYPE_LENGTH 16 +#define USB_BLOCK_HIGH_SPEED_SIZE 512 +#define DATA_SIZE 32768 +#define CMD_SIZE 512 +#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)
Parentheses around all Cmd and Buf instances in macro please?
+// The time between interrupt polls, in units of 100 nanoseconds +// 10 Microseconds +#define DW_INTERRUPT_POLL_PERIOD 10000
+EFI_GUID gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;
+STATIC dwc_otg_dev_dma_desc_t *gDmaDesc,*gDmaDescEp0,*gDmaDescIn; +STATIC USB_DEVICE_REQUEST *gCtrlReq; +STATIC VOID *RxBuf; +STATIC UINTN RxDescBytes = 0;
Static varibles are automatically initialised to 0.
+STATIC UINTN mNumDataBytes;
+STATIC DW_USB_PROTOCOL *DwUsb;
+STATIC USB_DEVICE_DESCRIPTOR *mDeviceDescriptor;
+// The config descriptor, interface descriptor, and endpoint descriptors in 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;
This is a huge amount of global static variables - could they be wrapped in a struct please? Also, this makes the driver hard-wired to only be able to support a single controller.
+/* To detect which mode was run, high speed or full speed */ +STATIC +UINTN +UsbDrvPortSpeed (
- VOID
- )
+{
- /*
- 2'b00: High speed (PHY clock is running at 30 or 60 MHz)
- */
- UINT32 Val = READ_REG32 (DSTS) & 2;
No magic numbers in code plese.
- return (!Val);
No need for the temporary variable.
+}
+STATIC +VOID +ResetEndpoints (
- VOID
- )
+{
- /* EP0 IN ACTIVE NEXT=1 */
- WRITE_REG32 (DIEPCTL0, DXEPCTL_USBACTEP | BIT11);
Can you create a more descriptive #define for that BIT11?
- /* EP0 OUT ACTIVE */
- WRITE_REG32 (DOEPCTL0, DXEPCTL_USBACTEP);
- /* Clear any pending OTG Interrupts */
- WRITE_REG32 (GOTGINT, ~0);
- /* Clear any pending interrupts */
- WRITE_REG32 (GINTSTS, ~0);
- WRITE_REG32 (DIEPINT0, ~0);
- WRITE_REG32 (DOEPINT0, ~0);
- WRITE_REG32 (DIEPINT1, ~0);
- WRITE_REG32 (DOEPINT1, ~0);
- /* IN EP interrupt mask */
- WRITE_REG32 (DIEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);
- /* OUT EP interrupt mask */
- WRITE_REG32 (DOEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);
- /* Enable interrupts on Ep0 */
- WRITE_REG32 (DAINTMSK, (1 << DAINTMSK_OUTEPMSK_SHIFT) | (1 << DAINTMSK_INEPMSK_SHIFT));
- /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/
- WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));
- //notes that:the compulsive conversion is expectable.
- gDmaDescEp0->status.b.bs = 0x3;
- gDmaDescEp0->status.b.mtrf = 0;
- gDmaDescEp0->status.b.sr = 0;
- gDmaDescEp0->status.b.l = 1;
- gDmaDescEp0->status.b.ioc = 1;
- gDmaDescEp0->status.b.sp = 0;
- gDmaDescEp0->status.b.bytes = 64;
- gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
Please drop the brackets around gCtrlReg. (Also future instances, including gDmaDescEp0 below.)
- gDmaDescEp0->status.b.sts = 0;
- gDmaDescEp0->status.b.bs = 0x0;
A lot of magic numbers above - please replace with #defines.
- WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
- /* EP0 OUT ENABLE CLEARNAK */
- WRITE_REG32 (DOEPCTL0, (READ_REG32 (DOEPCTL0) | DXEPCTL_EPENA | DXEPCTL_CNAK));
+}
+STATIC +VOID +EpTx (
- IN UINT8 Ep,
Is Ep shohrt for EndPoint? If so, please expand to the longer version. Preferably also in the function name. And for other functions in this driver.
- IN CONST VOID *Ptr,
- IN UINTN Len
- )
+{
- UINT32 BlockSize;
- UINT32 Packets;
- /* EPx OUT ACTIVE */
- WRITE_REG32 (DIEPCTL (Ep), (READ_REG32 (DIEPCTL (Ep))) | DXEPCTL_USBACTEP);
- if (!Ep) {
BlockSize = 64;
- } else {
BlockSize = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
- }
- Packets = (Len + BlockSize - 1) / BlockSize;
- if (!Len) {
/* send one empty packet */
gDmaDescIn->status.b.bs = 0x3;
gDmaDescIn->status.b.l = 1;
gDmaDescIn->status.b.ioc = 1;
gDmaDescIn->status.b.sp = 1;
gDmaDescIn->status.b.bytes = 0;
gDmaDescIn->buf = 0;
gDmaDescIn->status.b.sts = 0;
gDmaDescIn->status.b.bs = 0x0;
More magic numbers here, please replace with #defines.
WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn)); // DMA Address (DMAAddr) is zero
- } else {
WRITE_REG32 (DIEPTSIZ (Ep), Len | (Packets << 19));
"Len | (Packets << 19)" would be better to replace with a macro with a desriptive name.
//flush cache
WriteBackDataCacheRange ((VOID *)Ptr, Len);
gDmaDescIn->status.b.bs = 0x3;
gDmaDescIn->status.b.l = 1;
gDmaDescIn->status.b.ioc = 1;
gDmaDescIn->status.b.sp = 1;
gDmaDescIn->status.b.bytes = Len;
gDmaDescIn->buf = (UINT32)((UINTN)Ptr);
gDmaDescIn->status.b.sts = 0;
gDmaDescIn->status.b.bs = 0x0;
Magic numbers.
WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn)); // Ptr is DMA address
- }
- ArmDataSynchronizationBarrier ();
- /* epena & cnak */
- WRITE_REG32 (DIEPCTL (Ep), READ_REG32 (DIEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11);
+}
+STATIC +VOID +EpRx (
- IN UINTN Ep,
- IN UINTN Len
- )
+{
- /* EPx UNSTALL */
- WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & (~DXEPCTL_STALL)));
- /* EPx OUT ACTIVE */
- WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_USBACTEP));
Some macros would help make the above more readable.
- if (Len >= DATA_SIZE) {
- RxDescBytes = DATA_SIZE;
- } else {
- RxDescBytes = Len;
- }
- RxBuf = AllocatePool (DATA_SIZE);
- ASSERT (RxBuf != NULL);
Surely this should return rather than progress if running a RELEASE build?
- InvalidateDataCacheRange (RxBuf, Len);
- gDmaDesc->status.b.bs = 0x3;
- gDmaDesc->status.b.mtrf = 0;
- gDmaDesc->status.b.sr = 0;
- gDmaDesc->status.b.l = 1;
- gDmaDesc->status.b.ioc = 1;
- gDmaDesc->status.b.sp = 0;
- gDmaDesc->status.b.bytes = (UINT32)RxDescBytes;
- gDmaDesc->buf = (UINT32)((UINTN)RxBuf);
- gDmaDesc->status.b.sts = 0;
- gDmaDesc->status.b.bs = 0x0;
Lot of magic values.
- ArmDataSynchronizationBarrier ();
- WRITE_REG32 (DOEPDMA (Ep), (UINT32)((UINTN)gDmaDesc));
- /* EPx OUT ENABLE CLEARNAK */
- WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK));
Macros would help again, here.
+}
+STATIC +EFI_STATUS +HandleGetDescriptor (
- IN USB_DEVICE_REQUEST *Request
- )
+{
- UINT8 DescriptorType;
- UINTN ResponseSize;
- VOID *ResponseData;
- EFI_USB_STRING_DESCRIPTOR *Descriptor = NULL;
- UINTN DescriptorSize;
- ResponseSize = 0;
- ResponseData = NULL;
- // Pretty confused if bmRequestType is anything but this:
- ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE);
Return error instead?
- // Choose the response
- DescriptorType = Request->Value >> 8;
- switch (DescriptorType) {
- case USB_DESC_TYPE_DEVICE:
- DEBUG ((DEBUG_INFO, "USB: Got a request for device descriptor\n"));
"USB" is too generic an identifier for an error message. "DwUsbDxe" would be more appropriate for this driver, but preferably as a #define, and maybe hidden behind a local macro. (Comment applies globally to debug printouts in this driver.)
- ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);
- ResponseData = mDeviceDescriptor;
- break;
- case USB_DESC_TYPE_CONFIG:
- DEBUG ((DEBUG_INFO, "USB: Got a request for config descriptor\n"));
- ResponseSize = mConfigDescriptor->TotalLength;
- ResponseData = mDescriptors;
- break;
- case USB_DESC_TYPE_STRING:
- DEBUG ((DEBUG_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF));
- switch (Request->Value & 0xff) {
((x)->Value & 0xff) as a macro?
- case 0:
Please use defines rather than magic numbers.
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
LANG_LENGTH * sizeof (CHAR16) + 1;
Why "+ 1"? If CHAR16, should it not be "+ 2", or even better "+ sizeof (CHAR16)"? Same pattern repeats in many places in the file.
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
return error
Descriptor->Length = LANG_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetLang (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- case 1:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
return error I will stop repeating myself here. But please address: all ASSERTs that check whether a pointer is NULL before dereferencing it must return an error instead of triggering a synchronous exception at runtime in RELEASE builds.
Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- case 2:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
PRODUCT_STRING_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetProduct (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- case 3:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
SERIAL_STRING_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- }
- break;
- default:
- DEBUG ((DEBUG_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value));
- break;
- }
- // Send the response
- if (ResponseData) {
- ASSERT (ResponseSize != 0);
ResponseSize is set explicitly by the switch statement above. Rather than ASSERTing that it went wrong, why not return an error from the default target? You could then also drop the "if (ResponseData)" test, and the "if (Descriptor)" test below.
- if (Request->Length < ResponseSize) {
// Truncate response
ResponseSize = Request->Length;
- } else if (Request->Length > ResponseSize) {
DEBUG ((DEBUG_INFO, "USB: Info: ResponseSize < wLength\n"));
- }
- EpTx (0, ResponseData, ResponseSize);
- }
- if (Descriptor) {
Here.
- FreePool (Descriptor);
- }
- return EFI_SUCCESS;
+}
+STATIC +EFI_STATUS +HandleSetAddress (
- IN USB_DEVICE_REQUEST *Request
- )
+{
- // Pretty confused if bmRequestType is anything but this:
So is there any reason not to return an error?
- ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE);
- DEBUG ((DEBUG_INFO, "USB: Setting address to %d\n", Request->Value));
- ResetEndpoints ();
- WRITE_REG32 (DCFG, (READ_REG32 (DCFG) & ~DCFG_DEVADDR_MASK) | DCFG_DEVADDR(Request->Value));
- EpTx (0, 0, 0);
What is the significance of transmitting 0 bytes of data? Probably this should be replaced by a macro. And that macro should use NULL, not 0, for the invalid pointer.
- return EFI_SUCCESS;
+}
+STATIC +UINTN +UsbDrvRequestEndpoint (
- IN UINTN Type,
- IN UINTN Dir
- )
+{
- UINTN Ep = 1;
- UINTN Ret, NewBits;
- Ret = Ep | Dir;
- NewBits = (Type << 18) | 0x10000000;
No magic values, please. Replace with macro(s).
- /*
- (Type << 18):Endpoint Type (EPType)
- 0x10000000:Endpoint Enable (EPEna)
- 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.
- (ep<<22):TxFIFO Number (TxFNum)
- 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.
- */
- if (Dir) { // IN: to host
- WRITE_REG32 (DIEPCTL (Ep), ((READ_REG32 (DIEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits | (Ep << 22) | DXEPCTL_NAKSTS);
- } else { // OUT: to device
- WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits);
More macros, please. There WRITE_REG32 lines are unreadable.
- }
- return Ret;
+}
+STATIC +EFI_STATUS +HandleSetConfiguration (
- IN USB_DEVICE_REQUEST *Request
- )
+{
- ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE);
- // Cancel all transfers
- ResetEndpoints ();
- UsbDrvRequestEndpoint (2, 0);
- UsbDrvRequestEndpoint (2, 0x80);
No magic values, please.
- WRITE_REG32 (DIEPCTL1, (READ_REG32 (DIEPCTL1)) | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11);
What is this operation doing? Please simplify with a temporary variable and some more descriptive #defines.
- /* Enable interrupts on all endpoints */
- WRITE_REG32 (DAINTMSK, ~0);
- EpRx (1, CMD_SIZE);
The global variables also makes this code less readable.
- EpTx (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 = HandleGetDescriptor (Request);
- break;
- case USB_DEV_SET_ADDRESS:
- Status = HandleSetAddress (Request);
- break;
- case USB_DEV_SET_CONFIGURATION:
- Status = HandleSetConfiguration (Request);
- break;
- default:
- DEBUG ((DEBUG_ERROR,
"Didn't understand RequestType 0x%x Request 0x%x\n",
Request->RequestType, Request->Request));
Status = EFI_INVALID_PARAMETER;
- break;
- }
- return Status;
+}
+// Instead of actually registering interrupt handlers, we poll the controller's +// interrupt source register in this function. +STATIC +VOID +CheckInterrupts (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
+{
- UINT32 Ints, EpInts;
- // interrupt register
- Ints = READ_REG32 (GINTSTS);
- /*
- bus reset
- The core sets this bit to indicate that a reset is detected on the USB.
- */
- if (Ints & GINTSTS_USBRST) {
- WRITE_REG32 (DCFG, DCFG_DESCDMA | DCFG_NZ_STS_OUT_HSHK);
- ResetEndpoints ();
- }
- /*
- enumeration done, we now know the speed
- The core sets this bit to indicate that speed enumeration is complete. The
- application must read the Device Status (DSTS) register to obtain the
- enumerated speed.
- */
- if (Ints & GINTSTS_ENUMDONE) {
- /* Set up the maximum packet sizes accordingly */
- UINTN MaxPacket = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
A #define for that 64 please.
- //Set Maximum In Packet Size (MPS)
- WRITE_REG32 (DIEPCTL1, ((READ_REG32 (DIEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
- //Set Maximum Out Packet Size (MPS)
- WRITE_REG32 (DOEPCTL1, ((READ_REG32 (DOEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
This seems to be a recurring pattern, so should there be a macro UPDATE_REG32 (Regname, Mask, Value) ?
Alternatively, please use a temporary variable to do the read separately.
- }
- /*
- IN EP event
- The core sets this bit to indicate that an interrupt is pending on one of the IN
- endpoInts of the core (in Device mode). The application must read the
- Device All EndpoInts Interrupt (DAINT) register to determine the exact
- number of the IN endpoint on which the interrupt occurred, and then read
- the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to
- determine the exact cause of the interrupt. The application must clear the
- appropriate status bit in the corresponding DIEPINTn register to clear this bit.
- */
- if (Ints & GINTSTS_IEPINT) {
- EpInts = READ_REG32 (DIEPINT0);
- WRITE_REG32 (DIEPINT0, EpInts);
- if (EpInts & DXEPINT_XFERCOMPL) {
DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0)));
- }
- EpInts = READ_REG32 (DIEPINT1);
- WRITE_REG32 (DIEPINT1, EpInts);
- if (EpInts & DXEPINT_XFERCOMPL) {
DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n"));
- }
- }
Turn into helper function, please.
- /*
- OUT EP event
- The core sets this bit to indicate that an interrupt is pending on one of the
- OUT endpoints of the core (in Device mode). The application must read the
- Device All EndpoInts Interrupt (DAINT) register to determine the exact
- number of the OUT endpoint on which the interrupt occurred, and then read
- the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register
- to determine the exact cause of the interrupt. The application must clear the
- appropriate status bit in the corresponding DOEPINTn register to clear this bit.
- */
- if (Ints & GINTSTS_OEPINT) {
- /* indicates the status of an endpoint
* with respect to USB- and AHB-related events. */
- EpInts = READ_REG32 (DOEPINT0);
- if (EpInts) {
WRITE_REG32 (DOEPINT0, EpInts);
if (EpInts & DXEPINT_XFERCOMPL) {
DEBUG ((DEBUG_INFO, "INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32 (DOEPTSIZ0)));
}
/*
*
IN Token Received When TxFIFO is Empty (INTknTXFEmp)
* Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
* was empty. This interrupt is asserted on the endpoint for which the IN token
* was received.
*/
if (EpInts & BIT3) { /* SETUP phase done */
WRITE_REG32 (DIEPCTL0, READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK);
WRITE_REG32 (DOEPCTL0, READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK);
/*clear IN EP intr*/
WRITE_REG32 (DIEPINT0, ~0);
HandleDeviceRequest((USB_DEVICE_REQUEST *)gCtrlReq);
}
/* Make sure EP0 OUT is set up to accept the next request */
WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));
/*
* IN Token Received When TxFIFO is Empty (INTknTXFEmp)
* Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
* was empty. This interrupt is asserted on the endpoint for which the IN token
* was received.
*/
gDmaDescEp0->status.b.bs = 0x3;
gDmaDescEp0->status.b.mtrf = 0;
gDmaDescEp0->status.b.sr = 0;
gDmaDescEp0->status.b.l = 1;
gDmaDescEp0->status.b.ioc = 1;
gDmaDescEp0->status.b.sp = 0;
gDmaDescEp0->status.b.bytes = 64;
gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
gDmaDescEp0->status.b.sts = 0;
gDmaDescEp0->status.b.bs = 0x0;
WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
// endpoint enable; clear NAK
WRITE_REG32 (DOEPCTL0, DXEPCTL_EPENA | DXEPCTL_CNAK);
- }
- EpInts = (READ_REG32 (DOEPINT1));
- if (EpInts) {
WRITE_REG32 (DOEPINT1, EpInts);
/* Transfer Completed Interrupt (XferCompl);Transfer completed */
if (EpInts & DXEPINT_XFERCOMPL) {
UINTN Bytes = RxDescBytes - gDmaDesc->status.b.bytes;
UINTN Len = 0;
ArmDataSynchronizationBarrier ();
if (MATCH_CMD_LITERAL ("download", RxBuf)) {
mNumDataBytes = AsciiStrHexToUint64 (RxBuf + sizeof ("download"));
} else {
if (mNumDataBytes != 0) {
mNumDataBytes -= Bytes;
}
}
mDataReceivedCallback (Bytes, RxBuf);
if (mNumDataBytes == 0) {
Len = CMD_SIZE;
} else if (mNumDataBytes > DATA_SIZE) {
Len = DATA_SIZE;
} else {
Len = mNumDataBytes;
}
EpRx (1, Len);
}
- }
- }
Turn into helper function, please.
- //WRITE_REG32 clear ints
- WRITE_REG32 (GINTSTS, Ints);
+}
+EFI_STATUS +DwUsbSend (
- IN UINT8 EndpointIndex,
- IN UINTN Size,
- IN CONST VOID *Buffer
- )
+{
- EpTx (EndpointIndex, Buffer, Size);
- return EFI_SUCCESS;
+}
What is the purpose of this function?
+STATIC +VOID +DwUsbInit (
- VOID
- )
+{
- VOID *Buf;
- UINT32 Data;
- Buf = UncachedAllocatePages (16);
No magic values, please.
- gDmaDesc = Buf;
- gDmaDescEp0 = gDmaDesc + sizeof (dwc_otg_dev_dma_desc_t);
- gDmaDescIn = gDmaDescEp0 + sizeof (dwc_otg_dev_dma_desc_t);
- gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (dwc_otg_dev_dma_desc_t);
- ZeroMem (gDmaDesc, sizeof (dwc_otg_dev_dma_desc_t));
- ZeroMem (gDmaDescEp0, sizeof (dwc_otg_dev_dma_desc_t));
- ZeroMem (gDmaDescIn, sizeof (dwc_otg_dev_dma_desc_t));
Why not zero all of Buf once?
- /*Reset usb controller.*/
- /* Wait for OTG AHB master idle */
- do {
- Data = READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE;
- } while (Data == 0);
- /* OTG: Assert Software Reset */
- WRITE_REG32 (GRSTCTL, GRSTCTL_CSFTRST);
- /* Wait for OTG to ack reset */
- while (READ_REG32 (GRSTCTL) & GRSTCTL_CSFTRST);
- /* Wait for OTG AHB master idle */
- while ((READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE) == 0);
Second use of an explicit loop on this in this function - and coded differently to the first one. Turn into a macro instead?
- WRITE_REG32 (GDFIFOCFG, DATA_FIFO_CONFIG);
- WRITE_REG32 (GRXFSIZ, RX_SIZE);
- WRITE_REG32 (GNPTXFSIZ, ENDPOINT_TX_SIZE);
- WRITE_REG32 (DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);
- WRITE_REG32 (DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2);
- WRITE_REG32 (DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3);
- WRITE_REG32 (DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4);
- WRITE_REG32 (DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5);
- WRITE_REG32 (DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6);
- WRITE_REG32 (DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7);
- WRITE_REG32 (DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8);
- WRITE_REG32 (DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9);
- WRITE_REG32 (DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10);
- WRITE_REG32 (DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11);
- WRITE_REG32 (DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12);
- WRITE_REG32 (DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13);
- WRITE_REG32 (DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14);
- WRITE_REG32 (DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15);
- /*
- set Periodic TxFIFO Empty Level,
- Non-Periodic TxFIFO Empty Level,
- Enable DMA, Unmask Global Intr
- */
- WRITE_REG32 (GAHBCFG, GAHBCFG_CTRL_MASK);
- /*select 8bit UTMI+, ULPI Inerface*/
- WRITE_REG32 (GUSBCFG, 0x2400);
No magic numbers, please.
- /* Detect usb work mode,host or device? */
- do {
- Data = READ_REG32 (GINTSTS);
- } while (Data & GINTSTS_CURMODE_HOST);
- MicroSecondDelay (3);
Why a delay? Why 3us? Is a barrier needed?
- /*Init global and device mode csr register.*/
- /*set Non-Zero-Length status out handshake */
- Data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK;
No magic values, please.
- WRITE_REG32 (DCFG, Data);
- /* Interrupt unmask: IN event, OUT event, bus reset */
(And enumeration complete?)
- Data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE | GINTSTS_USBRST;
- WRITE_REG32 (GINTMSK, Data);
- do {
- Data = READ_REG32 (GINTSTS) & GINTSTS_ENUMDONE;
- } while (Data);
- /* Clear any pending OTG Interrupts */
- WRITE_REG32 (GOTGINT, ~0);
- /* Clear any pending interrupts */
- WRITE_REG32 (GINTSTS, ~0);
- WRITE_REG32 (GINTMSK, ~0);
- Data = READ_REG32 (GOTGINT);
- Data &= ~0x3000;
No magic values, please.
- WRITE_REG32 (GOTGINT, Data);
- /* endpoint settings cfg */
- ResetEndpoints ();
- MicroSecondDelay (1);
Why a delay? Why 1us? Is a barrier needed?
- /* init finish. and ready to transfer data */
- /* Soft Disconnect */
- WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE | DCTL_SFTDISCON);
- MicroSecondDelay (10000);
Why a delay? Why 10ms? Is a barrier needed?
- /* Soft Reconnect */
- WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE);
+}
+EFI_STATUS +EFIAPI +DwUsbStart (
- IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor,
- IN VOID **Descriptors,
- IN USB_DEVICE_RX_CALLBACK RxCallback,
- IN USB_DEVICE_TX_CALLBACK TxCallback
- )
+{
- UINT8 *Ptr;
- EFI_STATUS Status;
- EFI_EVENT TimerEvent;
- ASSERT (DeviceDescriptor != NULL);
- ASSERT (Descriptors[0] != NULL);
- ASSERT (RxCallback != NULL);
- ASSERT (TxCallback != NULL);
Can we do anything sane if any of these are NULL? If not, return error.
- DwUsbInit();
- mDeviceDescriptor = DeviceDescriptor;
- mDescriptors = Descriptors[0];
- // Right now we just support one configuration
- ASSERT (mDeviceDescriptor->NumConfigurations == 1);
- mDeviceDescriptor->StrManufacturer = 1;
- mDeviceDescriptor->StrProduct = 2;
- mDeviceDescriptor->StrSerialNumber = 3;
No magic values, please. Presumably these are just indexes into a string table, but use #defines please.
- // ... and one interface
- mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors;
- ASSERT (mConfigDescriptor->NumInterfaces == 1);
- Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR);
- mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr;
- Ptr += sizeof (USB_INTERFACE_DESCRIPTOR);
- mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr;
- mDataReceivedCallback = RxCallback;
- mDataSentCallback = TxCallback;
- // Register a timer event so CheckInterupts gets called periodically
- Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
CheckInterrupts,
NULL,
&TimerEvent
);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = gBS->SetTimer (
TimerEvent,
TimerPeriodic,
DW_INTERRUPT_POLL_PERIOD
);
- ASSERT_EFI_ERROR (Status);
- return Status;
+}
+USB_DEVICE_PROTOCOL mUsbDevice = {
- DwUsbStart,
- DwUsbSend
+};
+EFI_STATUS +EFIAPI +DwUsbEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
+{
- EFI_STATUS Status;
- Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = DwUsb->PhyInit(USB_DEVICE_MODE);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- return gBS->InstallProtocolInterface (
&ImageHandle,
&gUsbDeviceProtocolGuid,
EFI_NATIVE_INTERFACE,
&mUsbDevice
);
+} diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec new file mode 100644 index 0000000..f991492 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec @@ -0,0 +1,46 @@ +#/** @file +# Framework Module Development Environment Industry Standards +# +# This Package provides headers and libraries that conform to EFI/PI Industry standards. +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR> +# Copyright (c) 2015-2017, Linaro. All rights reserved.<BR> +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/
+[Defines]
- DEC_SPECIFICATION = 0x00010019
- PACKAGE_NAME = OpenPlatformDriversUsbDwUsbDxePkg
I think DwUsbDxePkg would be sufficient.
- PACKAGE_GUID = 114a3be9-10f7-4bf1-81ca-09ac52d4c3d5
- PACKAGE_VERSION = 0.1
+################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################
+[Guids.common]
- gAndroidFastbootUsbGuid = { 0xf6bec3fe, 0x88fb, 0x11e3, { 0xae, 0x84, 0xe7, 0x3b, 0x77, 0x56, 0x1c, 0x35 }}
Is this included only for the DEPEX? This does not feel like the right way of doing this.
- gDwUsbDxeTokenSpaceGuid = { 0x131c4d02, 0x9449, 0x4ee9, { 0xba, 0x3d, 0x69, 0x50, 0x21, 0x89, 0x26, 0x0b }}
+[Protocols.common]
- gDwUsbProtocolGuid = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
+[PcdsFixedAtBuild.common]
- # DwUsb Driver PCDs
- gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0x0|UINT32|0x00000001
- gDwUsbDxeTokenSpaceGuid.PcdSysCtrlBaseAddress|0x0|UINT32|0x00000002
I am really not happy about adding additional drivers with hard-coded base addresses. Especially not ones that claim to be DXE/UEFI drivers.
diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.h b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h new file mode 100644 index 0000000..7f909c3 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h @@ -0,0 +1,627 @@ +/** @file
- Copyright (c) 2015-2017, Linaro. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef __DW_USB_DXE_H__ +#define __DW_USB_DXE_H__
+#define DW_USB_BASE FixedPcdGet32 (PcdDwUsbDxeBaseAddress)
+#define READ_REG32(Offset) MmioRead32 (DW_USB_BASE + Offset) +#define READ_REG16(Offset) (UINT16)READ_REG32 (Offset) +#define WRITE_REG32(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, Val) +#define WRITE_REG16(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val) +#define WRITE_REG8(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val)
+// Max packet size in bytes (For Full Speed USB 64 is the only valid value) +#define MAX_PACKET_SIZE_CONTROL 64
+#define MAX_PACKET_SIZE_BULK 512
+// 8 Endpoints, in and out. Don't count the Endpoint 0 setup buffer +#define DW_NUM_ENDPOINTS 16
+// Endpoint Indexes +#define DW_EP0SETUP 0x20 +#define DW_EP0RX 0x00 +#define DW_EP0TX 0x01 +#define DW_EP1RX 0x02 +#define DW_EP1TX 0x03
+// DcInterrupt bits +#define DW_DC_INTERRUPT_EP1TX BIT13 +#define DW_DC_INTERRUPT_EP1RX BIT12 +#define DW_DC_INTERRUPT_EP0TX BIT11 +#define DW_DC_INTERRUPT_EP0RX BIT10 +#define DW_DC_INTERRUPT_EP0SETUP BIT8 +#define DW_DC_INTERRUPT_VBUS BIT7 +#define DW_DC_INTERRUPT_DMA BIT6 +#define DW_DC_INTERRUPT_HS_STAT BIT5 +#define DW_DC_INTERRUPT_RESUME BIT4 +#define DW_DC_INTERRUPT_SUSP BIT3 +#define DW_DC_INTERRUPT_PSOF BIT2 +#define DW_DC_INTERRUPT_SOF BIT1 +#define DW_DC_INTERRUPT_BRESET BIT0 +// All valid peripheral controller int rrupts +#define DW_DC_INTERRUPT_MASK 0x003FFFDFF
+#define DW_ADDRESS 0x200 +#define DW_ADDRESS_DEVEN BIT7
+#define DW_MODE 0x20C +#define DW_MODE_DATA_BUS_WIDTH BIT8 +#define DW_MODE_CLKAON BIT7 +#define DW_MODE_SFRESET BIT4 +#define DW_MODE_WKUPCS BIT2
+#define DW_ENDPOINT_MAX_PACKET_SIZE 0x204
+#define DW_ENDPOINT_TYPE 0x208 +#define DW_ENDPOINT_TYPE_NOEMPKT BIT4 +#define DW_ENDPOINT_TYPE_ENABLE BIT3
+#define DW_INTERRUPT_CONFIG 0x210 +// Interrupt config value to only interrupt on ACK of IN and OUT tokens +#define DW_INTERRUPT_CONFIG_ACK_ONLY (BIT2 | BIT5 | BIT6)
+#define DW_DC_INTERRUPT 0x218 +#define DW_DC_INTERRUPT_ENABLE 0x214
+#define DW_CTRL_FUNCTION 0x228 +#define DW_CTRL_FUNCTION_VENDP BIT3 +#define DW_CTRL_FUNCTION_DSEN BIT2 +#define DW_CTRL_FUNCTION_STATUS BIT1
+#define DW_DEVICE_UNLOCK 0x27C +#define DW_DEVICE_UNLOCK_MAGIC 0xAA37
+#define DW_SW_RESET_REG 0x30C +#define DW_SW_RESET_ALL BIT0
+#define DW_DEVICE_ID 0x370
+#define DW_OTG_CTRL_SET 0x374 +#define DW_OTG_CTRL_CLR (OTG_CTRL_SET + 2) +#define DW_OTG_CTRL_OTG_DISABLE BIT10 +#define DW_OTG_CTRL_VBUS_CHRG BIT6 +#define DW_OTG_CTRL_VBUS_DISCHRG BIT5 +#define DW_OTG_CTRL_DM_PULLDOWN BIT2 +#define DW_OTG_CTRL_DP_PULLDOWN BIT1 +#define DW_OTG_CTRL_DP_PULLUP BIT0
+#define DW_OTG_STATUS 0x378 +#define DW_OTG_STATUS_B_SESS_END BIT7 +#define DW_OTG_STATUS_A_B_SESS_VLD BIT1
+#define DW_OTG_INTERRUPT_LATCH_SET 0x37C +#define DW_OTG_INTERRUPT_LATCH_CLR 0x37E +#define DW_OTG_INTERRUPT_ENABLE_RISE 0x384
+#define DW_DMA_ENDPOINT_INDEX 0x258
+#define DW_ENDPOINT_INDEX 0x22c +#define DW_DATA_PORT 0x220 +#define DW_BUFFER_LENGTH 0x21c
+// Device ID Values +#define PHILLIPS_VENDOR_ID_VAL 0x04cc +#define DW_PRODUCT_ID_VAL 0x1761 +#define DW_DEVICE_ID_VAL ((ISP1761_PRODUCT_ID_VAL << 16) | \
PHILLIPS_VENDOR_ID_VAL)
+#define DWC_OTG_BASE DW_USB_BASE
+#define USB_NUM_ENDPOINTS 2 +#define MAX_EPS_CHANNELS 16
+#define BULK_OUT_EP 1 +#define BULK_IN_EP 1
+#define RX_REQ_LEN 512 +#define MAX_PACKET_LEN 512
+#define DATA_FIFO_CONFIG 0x0F801000 +/* RX FIFO: 2048 bytes */ +#define RX_SIZE 0x00000200 +/* Non-periodic TX FIFO: 128 bytes. start address: 0x200 * 4. */ +#define ENDPOINT_TX_SIZE 0x01000200
+/* EP1 TX FIFO: 1024 bytes. start address: 0x220 * 4. */ +/* EP2 TX FIFO: 1024 bytes. start address: 0x320 * 4. */ +/* EP3 TX FIFO: 1024 bytes. start address: 0x420 * 4. */ +/* EP4 TX FIFO: 1024 bytes. start address: 0x520 * 4. */ +/* EP5 TX FIFO: 128 bytes. start address: 0x620 * 4. */ +/* EP6 TX FIFO: 128 bytes. start address: 0x640 * 4. */ +/* EP7 TX FIFO: 128 bytes. start address: 0x660 * 4. */ +/* EP8 TX FIFO: 128 bytes. start address: 0x680 * 4. */ +/* EP9 TX FIFO: 128 bytes. start address: 0x6A0 * 4. */ +/* EP10 TX FIFO: 128 bytes. start address: 0x6C0 * 4. */ +/* EP11 TX FIFO: 128 bytes. start address: 0x6E0 * 4. */ +/* EP12 TX FIFO: 128 bytes. start address: 0x700 * 4. */ +/* EP13 TX FIFO: 128 bytes. start address: 0x720 * 4. */ +/* EP14 TX FIFO: 128 bytes. start address: 0x740 * 4. */ +/* EP15 TX FIFO: 128 bytes. start address: 0x760 * 4. */
+#define DATA_IN_ENDPOINT_TX_FIFO1 0x01000220 +#define DATA_IN_ENDPOINT_TX_FIFO2 0x01000320 +#define DATA_IN_ENDPOINT_TX_FIFO3 0x01000420 +#define DATA_IN_ENDPOINT_TX_FIFO4 0x01000520 +#define DATA_IN_ENDPOINT_TX_FIFO5 0x00200620 +#define DATA_IN_ENDPOINT_TX_FIFO6 0x00200640 +#define DATA_IN_ENDPOINT_TX_FIFO7 0x00200680 +#define DATA_IN_ENDPOINT_TX_FIFO8 0x002006A0 +#define DATA_IN_ENDPOINT_TX_FIFO9 0x002006C0 +#define DATA_IN_ENDPOINT_TX_FIFO10 0x002006E0 +#define DATA_IN_ENDPOINT_TX_FIFO11 0x00200700 +#define DATA_IN_ENDPOINT_TX_FIFO12 0x00200720 +#define DATA_IN_ENDPOINT_TX_FIFO13 0x00200740 +#define DATA_IN_ENDPOINT_TX_FIFO14 0x00200760 +#define DATA_IN_ENDPOINT_TX_FIFO15 0x00200F00
+/*DWC_OTG regsiter descriptor*/ +/*Device mode CSR MAP*/ +#define DEVICE_CSR_BASE 0x800 +/*Device mode CSR MAP*/ +#define DEVICE_INEP_BASE 0x900 +/*Device mode CSR MAP*/ +#define DEVICE_OUTEP_BASE 0xB00
+/*** OTG LINK CORE REGISTERS ***/ +/* Core Global Registers */ +#define GOTGCTL 0x000 +#define GOTGINT 0x004 +#define GAHBCFG 0x008 +#define GAHBCFG_P_TXF_EMP_LVL (1 << 8) +#define GAHBCFG_NP_TXF_EMP_LVL (1 << 7) +#define GAHBCFG_DMA_EN (1 << 5) +#define GAHBCFG_GLBL_INTR_EN (1 << 0) +#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \
GAHBCFG_NP_TXF_EMP_LVL | \
GAHBCFG_DMA_EN | \
GAHBCFG_GLBL_INTR_EN)
+#define GUSBCFG 0x00C +#define GRSTCTL 0x010 +#define GRSTCTL_AHBIDLE (1 << 31) +#define GRSTCTL_CSFTRST (1 << 0)
+#define GINTSTS 0x014 +#define GINTSTS_WKUPINT BIT31 +#define GINTSTS_SESSREGINT BIT30 +#define GINTSTS_DISCONNINT BIT29 +#define GINTSTS_CONIDSTSCHNG BIT28 +#define GINTSTS_LPMTRANRCVD BIT27 +#define GINTSTS_PTXFEMP BIT26 +#define GINTSTS_HCHINT BIT25 +#define GINTSTS_PRTINT BIT24 +#define GINTSTS_RESETDET BIT23 +#define GINTSTS_FET_SUSP BIT22 +#define GINTSTS_INCOMPL_IP BIT21 +#define GINTSTS_INCOMPL_SOIN BIT20 +#define GINTSTS_OEPINT BIT19 +#define GINTSTS_IEPINT BIT18 +#define GINTSTS_EPMIS BIT17 +#define GINTSTS_RESTOREDONE BIT16 +#define GINTSTS_EOPF BIT15 +#define GINTSTS_ISOUTDROP BIT14 +#define GINTSTS_ENUMDONE BIT13 +#define GINTSTS_USBRST BIT12 +#define GINTSTS_USBSUSP BIT11 +#define GINTSTS_ERLYSUSP BIT10 +#define GINTSTS_I2CINT BIT9 +#define GINTSTS_ULPI_CK_INT BIT8 +#define GINTSTS_GOUTNAKEFF BIT7 +#define GINTSTS_GINNAKEFF BIT6 +#define GINTSTS_NPTXFEMP BIT5 +#define GINTSTS_RXFLVL BIT4 +#define GINTSTS_SOF BIT3 +#define GINTSTS_OTGINT BIT2 +#define GINTSTS_MODEMIS BIT1 +#define GINTSTS_CURMODE_HOST BIT0
+#define GINTMSK 0x018 +#define GRXSTSR 0x01C +#define GRXSTSP 0x020 +#define GRXFSIZ 0x024 +#define GNPTXFSIZ 0x028 +#define GNPTXSTS 0x02C
+#define GHWCFG1 0x044 +#define GHWCFG2 0x048 +#define GHWCFG3 0x04c +#define GHWCFG4 0x050 +#define GLPMCFG 0x054
+#define GDFIFOCFG 0x05c
+#define HPTXFSIZ 0x100 +#define DIEPTXF(x) (0x100 + 4 * (x)) +#define DIEPTXF1 0x104 +#define DIEPTXF2 0x108 +#define DIEPTXF3 0x10C +#define DIEPTXF4 0x110 +#define DIEPTXF5 0x114 +#define DIEPTXF6 0x118 +#define DIEPTXF7 0x11C +#define DIEPTXF8 0x120 +#define DIEPTXF9 0x124 +#define DIEPTXF10 0x128 +#define DIEPTXF11 0x12C +#define DIEPTXF12 0x130 +#define DIEPTXF13 0x134 +#define DIEPTXF14 0x138 +#define DIEPTXF15 0x13C
+/*** HOST MODE REGISTERS ***/ +/* Host Global Registers */ +#define HCFG 0x400 +#define HFIR 0x404 +#define HFNUM 0x408 +#define HPTXSTS 0x410 +#define HAINT 0x414 +#define HAINTMSK 0x418
+/* Host Port Control and Status Registers */ +#define HPRT 0x440
+/* Host Channel-Specific Registers */ +#define HCCHAR(x) (0x500 + 0x20 * (x)) +#define HCSPLT(x) (0x504 + 0x20 * (x)) +#define HCINT(x) (0x508 + 0x20 * (x)) +#define HCINTMSK(x) (0x50C + 0x20 * (x)) +#define HCTSIZ(x) (0x510 + 0x20 * (x)) +#define HCDMA(x) (0x514 + 0x20 * (x)) +#define HCCHAR0 0x500 +#define HCSPLT0 0x504 +#define HCINT0 0x508 +#define HCINTMSK0 0x50C +#define HCTSIZ0 0x510 +#define HCDMA0 0x514 +#define HCCHAR1 0x520 +#define HCSPLT1 0x524 +#define HCINT1 0x528 +#define HCINTMSK1 0x52C +#define HCTSIZ1 0x530 +#define HCDMA1 0x534 +#define HCCHAR2 0x540 +#define HCSPLT2 0x544 +#define HCINT2 0x548 +#define HCINTMSK2 0x54C +#define HCTSIZ2 0x550 +#define HCDMA2 0x554 +#define HCCHAR3 0x560 +#define HCSPLT3 0x564 +#define HCINT3 0x568 +#define HCINTMSK3 0x56C +#define HCTSIZ3 0x570 +#define HCDMA3 0x574 +#define HCCHAR4 0x580 +#define HCSPLT4 0x584 +#define HCINT4 0x588 +#define HCINTMSK4 0x58C +#define HCTSIZ4 0x590 +#define HCDMA4 0x594 +#define HCCHAR5 0x5A0 +#define HCSPLT5 0x5A4 +#define HCINT5 0x5A8 +#define HCINTMSK5 0x5AC +#define HCTSIZ5 0x5B0 +#define HCDMA5 0x5B4 +#define HCCHAR6 0x5C0 +#define HCSPLT6 0x5C4 +#define HCINT6 0x5C8 +#define HCINTMSK6 0x5CC +#define HCTSIZ6 0x5D0 +#define HCDMA6 0x5D4 +#define HCCHAR7 0x5E0 +#define HCSPLT7 0x5E4 +#define HCINT7 0x5E8 +#define HCINTMSK7 0x5EC +#define HCTSIZ7 0x5F0 +#define HCDMA7 0x5F4 +#define HCCHAR8 0x600 +#define HCSPLT8 0x604 +#define HCINT8 0x608 +#define HCINTMSK8 0x60C +#define HCTSIZ8 0x610 +#define HCDMA8 0x614 +#define HCCHAR9 0x620 +#define HCSPLT9 0x624 +#define HCINT9 0x628 +#define HCINTMSK9 0x62C +#define HCTSIZ9 0x630 +#define HCDMA9 0x634 +#define HCCHAR10 0x640 +#define HCSPLT10 0x644 +#define HCINT10 0x648 +#define HCINTMSK10 0x64C +#define HCTSIZ10 0x650 +#define HCDMA10 0x654 +#define HCCHAR11 0x660 +#define HCSPLT11 0x664 +#define HCINT11 0x668 +#define HCINTMSK11 0x66C +#define HCTSIZ11 0x670 +#define HCDMA11 0x674 +#define HCCHAR12 0x680 +#define HCSPLT12 0x684 +#define HCINT12 0x688 +#define HCINTMSK12 0x68C +#define HCTSIZ12 0x690 +#define HCDMA12 0x694 +#define HCCHAR13 0x6A0 +#define HCSPLT13 0x6A4 +#define HCINT13 0x6A8 +#define HCINTMSK13 0x6AC +#define HCTSIZ13 0x6B0 +#define HCDMA13 0x6B4 +#define HCCHAR14 0x6C0 +#define HCSPLT14 0x6C4 +#define HCINT14 0x6C8 +#define HCINTMSK14 0x6CC +#define HCTSIZ14 0x6D0 +#define HCDMA14 0x6D4 +#define HCCHAR15 0x6E0 +#define HCSPLT15 0x6E4 +#define HCINT15 0x6E8 +#define HCINTMSK15 0x6EC +#define HCTSIZ15 0x6F0 +#define HCDMA15 0x6F4
+/*** DEVICE MODE REGISTERS ***/ +/* Device Global Registers */ +#define DCFG 0x800 +#define DCFG_DESCDMA BIT23 +#define DCFG_EPMISCNT_MASK (0x1F << 18) +#define DCFG_EPMISCNT_SHIFT 18 +#define DCFG_DEVADDR_MASK (0x7F << 4) +#define DCFG_DEVADDR_SHIFT 4 +#define DCFG_DEVADDR(x) (((x) << DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK) +#define DCFG_NZ_STS_OUT_HSHK BIT2
+#define DCTL 0x804 +#define DCTL_PWRONPRGDONE BIT11 +#define DCTL_GNPINNAKSTS BIT2 +#define DCTL_SFTDISCON BIT1
+#define DSTS 0x808 +#define DIEPMSK 0x810 +#define DOEPMSK 0x814
+#define DXEPMSK_TIMEOUTMSK BIT3 +#define DXEPMSK_AHBERMSK BIT2 +#define DXEPMSK_XFERCOMPLMSK BIT0
+#define DAINT 0x818 +#define DAINTMSK 0x81C
+#define DAINTMSK_OUTEPMSK_SHIFT 16 +#define DAINTMSK_INEPMSK_SHIFT 0
+#define DTKNQR1 0x820 +#define DTKNQR2 0x824 +#define DVBUSDIS 0x828 +#define DVBUSPULSE 0x82C +#define DTHRCTL 0x830
+/* Device Logical IN Endpoint-Specific Registers */ +#define DIEPCTL(x) (0x900 + 0x20 * (x)) +#define DIEPINT(x) (0x908 + 0x20 * (x)) +#define DIEPTSIZ(x) (0x910 + 0x20 * (x)) +#define DIEPDMA(x) (0x914 + 0x20 * (x)) +#define DTXFSTS(x) (0x918 + 0x20 * (x))
+#define DIEPCTL0 0x900 +#define DIEPINT0 0x908 +#define DIEPTSIZ0 0x910 +#define DIEPDMA0 0x914 +#define DIEPCTL1 0x920 +#define DIEPINT1 0x928 +#define DIEPTSIZ1 0x930 +#define DIEPDMA1 0x934 +#define DIEPCTL2 0x940 +#define DIEPINT2 0x948 +#define DIEPTSIZ2 0x950 +#define DIEPDMA2 0x954 +#define DIEPCTL3 0x960 +#define DIEPINT3 0x968 +#define DIEPTSIZ3 0x970 +#define DIEPDMA3 0x974 +#define DIEPCTL4 0x980 +#define DIEPINT4 0x988 +#define DIEPTSIZ4 0x990 +#define DIEPDMA4 0x994 +#define DIEPCTL5 0x9A0 +#define DIEPINT5 0x9A8 +#define DIEPTSIZ5 0x9B0 +#define DIEPDMA5 0x9B4 +#define DIEPCTL6 0x9C0 +#define DIEPINT6 0x9C8 +#define DIEPTSIZ6 0x9D0 +#define DIEPDMA6 0x9D4 +#define DIEPCTL7 0x9E0 +#define DIEPINT7 0x9E8 +#define DIEPTSIZ7 0x9F0 +#define DIEPDMA7 0x9F4 +#define DIEPCTL8 0xA00 +#define DIEPINT8 0xA08 +#define DIEPTSIZ8 0xA10 +#define DIEPDMA8 0xA14 +#define DIEPCTL9 0xA20 +#define DIEPINT9 0xA28 +#define DIEPTSIZ9 0xA30 +#define DIEPDMA9 0xA34 +#define DIEPCTL10 0xA40 +#define DIEPINT10 0xA48 +#define DIEPTSIZ10 0xA50 +#define DIEPDMA10 0xA54 +#define DIEPCTL11 0xA60 +#define DIEPINT11 0xA68 +#define DIEPTSIZ11 0xA70 +#define DIEPDMA11 0xA74 +#define DIEPCTL12 0xA80 +#define DIEPINT12 0xA88 +#define DIEPTSIZ12 0xA90 +#define DIEPDMA12 0xA94 +#define DIEPCTL13 0xAA0 +#define DIEPINT13 0xAA8 +#define DIEPTSIZ13 0xAB0 +#define DIEPDMA13 0xAB4 +#define DIEPCTL14 0xAC0 +#define DIEPINT14 0xAC8 +#define DIEPTSIZ14 0xAD0 +#define DIEPDMA14 0xAD4 +#define DIEPCTL15 0xAE0 +#define DIEPINT15 0xAE8 +#define DIEPTSIZ15 0xAF0 +#define DIEPDMA15 0xAF4
+/* Device Logical OUT Endpoint-Specific Registers */ +#define DOEPCTL(x) (0xB00 + 0x20 * (x)) +#define DOEPINT(x) (0xB08 + 0x20 * (x)) +#define DOEPTSIZ(x) (0xB10 + 0x20 * (x))
+#define DXEPINT_EPDISBLD BIT1 +#define DXEPINT_XFERCOMPL BIT0
+#define DXEPTSIZ_SUPCNT(x) (((x) & 0x3) << 29) +#define DXEPTSIZ_PKTCNT(x) (((x) & 0x3) << 19) +#define DXEPTSIZ_XFERSIZE(x) ((x) & 0x7F)
+#define DOEPDMA(x) (0xB14 + 0x20 * (x)) +#define DOEPCTL0 0xB00 +#define DOEPINT0 0xB08 +#define DOEPTSIZ0 0xB10 +#define DOEPDMA0 0xB14 +#define DOEPCTL1 0xB20 +#define DOEPINT1 0xB28 +#define DOEPTSIZ1 0xB30 +#define DOEPDMA1 0xB34 +#define DOEPCTL2 0xB40 +#define DOEPINT2 0xB48 +#define DOEPTSIZ2 0xB50 +#define DOEPDMA2 0xB54 +#define DOEPCTL3 0xB60 +#define DOEPINT3 0xB68 +#define DOEPTSIZ3 0xB70 +#define DOEPDMA3 0xB74 +#define DOEPCTL4 0xB80 +#define DOEPINT4 0xB88 +#define DOEPTSIZ4 0xB90 +#define DOEPDMA4 0xB94 +#define DOEPCTL5 0xBA0 +#define DOEPINT5 0xBA8 +#define DOEPTSIZ5 0xBB0 +#define DOEPDMA5 0xBB4 +#define DOEPCTL6 0xBC0 +#define DOEPINT6 0xBC8 +#define DOEPTSIZ6 0xBD0 +#define DOEPDMA6 0xBD4 +#define DOEPCTL7 0xBE0 +#define DOEPINT7 0xBE8 +#define DOEPTSIZ7 0xBF0 +#define DOEPDMA7 0xBF4 +#define DOEPCTL8 0xC00 +#define DOEPINT8 0xC08 +#define DOEPTSIZ8 0xC10 +#define DOEPDMA8 0xC14 +#define DOEPCTL9 0xC20 +#define DOEPINT9 0xC28 +#define DOEPTSIZ9 0xC30 +#define DOEPDMA9 0xC34 +#define DOEPCTL10 0xC40 +#define DOEPINT10 0xC48 +#define DOEPTSIZ10 0xC50 +#define DOEPDMA10 0xC54 +#define DOEPCTL11 0xC60 +#define DOEPINT11 0xC68 +#define DOEPTSIZ11 0xC70 +#define DOEPDMA11 0xC74 +#define DOEPCTL12 0xC80 +#define DOEPINT12 0xC88 +#define DOEPTSIZ12 0xC90 +#define DOEPDMA12 0xC94 +#define DOEPCTL13 0xCA0 +#define DOEPINT13 0xCA8 +#define DOEPTSIZ13 0xCB0 +#define DOEPDMA13 0xCB4 +#define DOEPCTL14 0xCC0 +#define DOEPINT14 0xCC8 +#define DOEPTSIZ14 0xCD0 +#define DOEPDMA14 0xCD4 +#define DOEPCTL15 0xCE0 +#define DOEPINT15 0xCE8 +#define DOEPTSIZ15 0xCF0 +#define DOEPDMA15 0xCF4
+#define DXEPCTL_EPENA BIT31 +#define DXEPCTL_SNAK BIT27 +#define DXEPCTL_CNAK BIT26 +#define DXEPCTL_STALL BIT21 +#define DXEPCTL_EPTYPE_MASK (BIT19 | BIT18) +#define DXEPCTL_NAKSTS BIT17 +#define DXEPCTL_USBACTEP BIT15 +#define DXEPCTL_MPS_MASK 0x7FF
+/* Power and Clock Gating Register */ +#define PCGCCTL 0xE00
+#define EP0FIFO 0x1000
+/**
- This union represents the bit fields in the DMA Descriptor
- status quadlet. Read the quadlet into the <i>d32</i> member then
- set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
- <i>b_iso_in</i> elements.
- */
+typedef union {
- /** raw register data */
- UINT32 d32;
- /** quadlet bits */
- struct {
- /** Received number of bytes */
- unsigned bytes:16;
- /** NAK bit - only for OUT EPs */
- unsigned nak:1;
- unsigned reserved17_22:6;
- /** Multiple Transfer - only for OUT EPs */
- unsigned mtrf:1;
- /** Setup Packet received - only for OUT EPs */
- unsigned sr:1;
- /** Interrupt On Complete */
- unsigned ioc:1;
- /** Short Packet */
- unsigned sp:1;
- /** Last */
- unsigned l:1;
- /** Receive Status */
- unsigned sts:2;
- /** Buffer Status */
- unsigned bs:2;
- } b;
+} dev_dma_desc_sts_t;
+/**
- DMA Descriptor structure
- DMA Descriptor structure contains two quadlets:
- Status quadlet and Data buffer pointer.
- */
+typedef struct {
- /** DMA Descriptor status quadlet */
- dev_dma_desc_sts_t status;
- /** DMA Descriptor data buffer pointer */
- UINT32 buf;
+} dwc_otg_dev_dma_desc_t;
The above union and struct do not conform to EDK2 coding style.
+#endif //ifndef __DW_USB_DXE_H__ diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf new file mode 100644 index 0000000..fc1e988 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf @@ -0,0 +1,52 @@ +#/** @file +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/
+[Defines]
- INF_VERSION = 0x00010019
- BASE_NAME = DwUsbDxe
- FILE_GUID = 72d78ea6-4dee-11e3-8100-f3842a48d0a0
- MODULE_TYPE = UEFI_DRIVER
I don't believe the driver in its current state can be called a UEFI_DRIVER. Combined with the ordering issue, should this be a DXE_DRIVER instead?
- VERSION_STRING = 1.0
- ENTRY_POINT = DwUsbEntryPoint
+[Sources.common]
- DwUsbDxe.c
+[LibraryClasses]
- ArmLib
- DebugLib
- IoLib
- MemoryAllocationLib
- TimerLib
- UefiBootServicesTableLib
- UefiDriverEntryPoint
- UncachedMemoryAllocationLib
- CacheMaintenanceLib
Please sort LibraryClasses.
+[Protocols]
- gEfiDriverBindingProtocolGuid
- gUsbDeviceProtocolGuid
+[Packages]
- ArmPkg/ArmPkg.dec
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- EmbeddedPkg/EmbeddedPkg.dec
- OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
Please sort Packages.
/ Leif
+[Pcd]
- gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress
+[Depex]
- BEFORE gAndroidFastbootUsbGuid
diff --git a/Include/Protocol/DwUsb.h b/Include/Protocol/DwUsb.h new file mode 100644 index 0000000..040e126 --- /dev/null +++ b/Include/Protocol/DwUsb.h @@ -0,0 +1,81 @@ +/** @file
- Copyright (c) 2015-2017, Linaro. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef __DW_USB_H__ +#define __DW_USB_H__
+// +// Protocol GUID +// +#define DW_USB_PROTOCOL_GUID { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
+// +// Protocol interface structure +// +typedef struct _DW_USB_PROTOCOL DW_USB_PROTOCOL;
+#define USB_HOST_MODE 0 +#define USB_DEVICE_MODE 1 +#define USB_CABLE_NOT_ATTACHED 2
+#define LANG_LENGTH 8 +#define MANU_FACTURER_STRING_LENGTH 32 +#define PRODUCT_STRING_LENGTH 32 +#define SERIAL_STRING_LENGTH 17
+typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_LANG) (
- OUT CHAR16 *Lang,
- OUT UINT8 *Length
- );
+typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_MANU_FACTURER) (
- OUT CHAR16 *ManuFacturer,
- OUT UINT8 *Length
- );
+typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_PRODUCT) (
- OUT CHAR16 *Product,
- OUT UINT8 *Length
- );
+typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_SERIAL_NO) (
- OUT CHAR16 *SerialNo,
- OUT UINT8 *Length
- );
+typedef +EFI_STATUS +(EFIAPI *DW_USB_PHY_INIT) (
- IN UINT8 Mode
- );
+struct _DW_USB_PROTOCOL {
- DW_USB_GET_LANG GetLang;
- DW_USB_GET_MANU_FACTURER GetManuFacturer;
- DW_USB_GET_PRODUCT GetProduct;
- DW_USB_GET_SERIAL_NO GetSerialNo;
- DW_USB_PHY_INIT PhyInit;
+};
+extern EFI_GUID gDwUsbProtocolGuid;
+#endif
2.7.4
On 8 February 2017 at 00:45, Leif Lindholm leif.lindholm@linaro.org wrote:
On Sat, Feb 04, 2017 at 01:13:48PM +0800, Haojian Zhuang wrote:
Support Designware USB controller.
A bit more detailed commit message please - which USB controller, which USB standards does it support?
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org
Drivers/Usb/DwUsbDxe/DwUsbDxe.c | 796 ++++++++++++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.dec | 46 +++ Drivers/Usb/DwUsbDxe/DwUsbDxe.h | 627 ++++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.inf | 52 +++ Include/Protocol/DwUsb.h | 81 ++++ 5 files changed, 1602 insertions(+) create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.c create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.dec create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.h create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.inf create mode 100644 Include/Protocol/DwUsb.h
diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.c b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c new file mode 100644 index 0000000..bdd8405 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c @@ -0,0 +1,796 @@ +/** @file
- Copyright (c) 2015-2017, Linaro. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <IndustryStandard/Usb.h> +#include <Library/ArmLib.h> +#include <Library/TimerLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UncachedMemoryAllocationLib.h> +#include <Library/CacheMaintenanceLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/BaseLib.h> +#include <Protocol/DwUsb.h> +#include <Protocol/UsbDevice.h>
Please sort include files alphabetically.
Fixed in v4 already.
+#include "DwUsbDxe.h"
+#define USB_TYPE_LENGTH 16 +#define USB_BLOCK_HIGH_SPEED_SIZE 512 +#define DATA_SIZE 32768 +#define CMD_SIZE 512 +#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)
Parentheses around all Cmd and Buf instances in macro please?
Fixed in v4 already.
+// The time between interrupt polls, in units of 100 nanoseconds +// 10 Microseconds +#define DW_INTERRUPT_POLL_PERIOD 10000
+EFI_GUID gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;
+STATIC dwc_otg_dev_dma_desc_t *gDmaDesc,*gDmaDescEp0,*gDmaDescIn; +STATIC USB_DEVICE_REQUEST *gCtrlReq; +STATIC VOID *RxBuf; +STATIC UINTN RxDescBytes = 0;
Static varibles are automatically initialised to 0.
Fixed in v4 already.
+STATIC UINTN mNumDataBytes;
+STATIC DW_USB_PROTOCOL *DwUsb;
+STATIC USB_DEVICE_DESCRIPTOR *mDeviceDescriptor;
+// The config descriptor, interface descriptor, and endpoint descriptors in 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;
This is a huge amount of global static variables - could they be wrapped in a struct please? Also, this makes the driver hard-wired to only be able to support a single controller.
Actually it's impossible to run two or more usb devices at the same time. It's different from USB host.
+/* To detect which mode was run, high speed or full speed */ +STATIC +UINTN +UsbDrvPortSpeed (
- VOID
- )
+{
- /*
- 2'b00: High speed (PHY clock is running at 30 or 60 MHz)
- */
- UINT32 Val = READ_REG32 (DSTS) & 2;
No magic numbers in code plese.
Fixed in v4 already.
- return (!Val);
No need for the temporary variable.
Fixed in v4 already.
+}
+STATIC +VOID +ResetEndpoints (
- VOID
- )
+{
- /* EP0 IN ACTIVE NEXT=1 */
- WRITE_REG32 (DIEPCTL0, DXEPCTL_USBACTEP | BIT11);
Can you create a more descriptive #define for that BIT11?
I don't know this bit. Nobody share the bit definition to me.
- //notes that:the compulsive conversion is expectable.
- gDmaDescEp0->status.b.bs = 0x3;
- gDmaDescEp0->status.b.mtrf = 0;
- gDmaDescEp0->status.b.sr = 0;
- gDmaDescEp0->status.b.l = 1;
- gDmaDescEp0->status.b.ioc = 1;
- gDmaDescEp0->status.b.sp = 0;
- gDmaDescEp0->status.b.bytes = 64;
- gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
Please drop the brackets around gCtrlReg. (Also future instances, including gDmaDescEp0 below.)
Fixed in v4 already.
- gDmaDescEp0->status.b.sts = 0;
- gDmaDescEp0->status.b.bs = 0x0;
A lot of magic numbers above - please replace with #defines.
I don't have the details on these bits.
- WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
- /* EP0 OUT ENABLE CLEARNAK */
- WRITE_REG32 (DOEPCTL0, (READ_REG32 (DOEPCTL0) | DXEPCTL_EPENA | DXEPCTL_CNAK));
+}
+STATIC +VOID +EpTx (
- IN UINT8 Ep,
Is Ep shohrt for EndPoint? If so, please expand to the longer version. Preferably also in the function name. And for other functions in this driver.
Fixed in v4 already.
- IN CONST VOID *Ptr,
- IN UINTN Len
- )
+{
- UINT32 BlockSize;
- UINT32 Packets;
- /* EPx OUT ACTIVE */
- WRITE_REG32 (DIEPCTL (Ep), (READ_REG32 (DIEPCTL (Ep))) | DXEPCTL_USBACTEP);
- if (!Ep) {
BlockSize = 64;
- } else {
BlockSize = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
- }
- Packets = (Len + BlockSize - 1) / BlockSize;
- if (!Len) {
/* send one empty packet */
gDmaDescIn->status.b.bs = 0x3;
gDmaDescIn->status.b.l = 1;
gDmaDescIn->status.b.ioc = 1;
gDmaDescIn->status.b.sp = 1;
gDmaDescIn->status.b.bytes = 0;
gDmaDescIn->buf = 0;
gDmaDescIn->status.b.sts = 0;
gDmaDescIn->status.b.bs = 0x0;
More magic numbers here, please replace with #defines.
I don't have any details on these.
WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn)); // DMA Address (DMAAddr) is zero
- } else {
WRITE_REG32 (DIEPTSIZ (Ep), Len | (Packets << 19));
"Len | (Packets << 19)" would be better to replace with a macro with a desriptive name.
Fixed in v4 already.
//flush cache
WriteBackDataCacheRange ((VOID *)Ptr, Len);
gDmaDescIn->status.b.bs = 0x3;
gDmaDescIn->status.b.l = 1;
gDmaDescIn->status.b.ioc = 1;
gDmaDescIn->status.b.sp = 1;
gDmaDescIn->status.b.bytes = Len;
gDmaDescIn->buf = (UINT32)((UINTN)Ptr);
gDmaDescIn->status.b.sts = 0;
gDmaDescIn->status.b.bs = 0x0;
Magic numbers.
Yes, but I don't have any details.
WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn)); // Ptr is DMA address
- }
- ArmDataSynchronizationBarrier ();
- /* epena & cnak */
- WRITE_REG32 (DIEPCTL (Ep), READ_REG32 (DIEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11);
+}
+STATIC +VOID +EpRx (
- IN UINTN Ep,
- IN UINTN Len
- )
+{
- /* EPx UNSTALL */
- WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & (~DXEPCTL_STALL)));
- /* EPx OUT ACTIVE */
- WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_USBACTEP));
Some macros would help make the above more readable.
- if (Len >= DATA_SIZE) {
- RxDescBytes = DATA_SIZE;
- } else {
- RxDescBytes = Len;
- }
- RxBuf = AllocatePool (DATA_SIZE);
- ASSERT (RxBuf != NULL);
Surely this should return rather than progress if running a RELEASE build?
Fixed in v4 already.
- InvalidateDataCacheRange (RxBuf, Len);
- gDmaDesc->status.b.bs = 0x3;
- gDmaDesc->status.b.mtrf = 0;
- gDmaDesc->status.b.sr = 0;
- gDmaDesc->status.b.l = 1;
- gDmaDesc->status.b.ioc = 1;
- gDmaDesc->status.b.sp = 0;
- gDmaDesc->status.b.bytes = (UINT32)RxDescBytes;
- gDmaDesc->buf = (UINT32)((UINTN)RxBuf);
- gDmaDesc->status.b.sts = 0;
- gDmaDesc->status.b.bs = 0x0;
Lot of magic values.
Yes, but I don't have the details on these bits.
- ArmDataSynchronizationBarrier ();
- WRITE_REG32 (DOEPDMA (Ep), (UINT32)((UINTN)gDmaDesc));
- /* EPx OUT ENABLE CLEARNAK */
- WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK));
Macros would help again, here.
+}
+STATIC +EFI_STATUS +HandleGetDescriptor (
- IN USB_DEVICE_REQUEST *Request
- )
+{
- UINT8 DescriptorType;
- UINTN ResponseSize;
- VOID *ResponseData;
- EFI_USB_STRING_DESCRIPTOR *Descriptor = NULL;
- UINTN DescriptorSize;
- ResponseSize = 0;
- ResponseData = NULL;
- // Pretty confused if bmRequestType is anything but this:
- ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE);
Return error instead?
Fixed in v4 already.
- // Choose the response
- DescriptorType = Request->Value >> 8;
- switch (DescriptorType) {
- case USB_DESC_TYPE_DEVICE:
- DEBUG ((DEBUG_INFO, "USB: Got a request for device descriptor\n"));
"USB" is too generic an identifier for an error message. "DwUsbDxe" would be more appropriate for this driver, but preferably as a #define, and maybe hidden behind a local macro. (Comment applies globally to debug printouts in this driver.)
Fixed in v4 already.
- ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);
- ResponseData = mDeviceDescriptor;
- break;
- case USB_DESC_TYPE_CONFIG:
- DEBUG ((DEBUG_INFO, "USB: Got a request for config descriptor\n"));
- ResponseSize = mConfigDescriptor->TotalLength;
- ResponseData = mDescriptors;
- break;
- case USB_DESC_TYPE_STRING:
- DEBUG ((DEBUG_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF));
- switch (Request->Value & 0xff) {
((x)->Value & 0xff) as a macro?
Fixed in v4 already.
- case 0:
Please use defines rather than magic numbers.
OK
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
LANG_LENGTH * sizeof (CHAR16) + 1;
Why "+ 1"? If CHAR16, should it not be "+ 2", or even better "+ sizeof (CHAR16)"? Same pattern repeats in many places in the file.
OK
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
return error
Fixed in v4 already.
Descriptor->Length = LANG_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetLang (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- case 1:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
return error I will stop repeating myself here. But please address: all ASSERTs that check whether a pointer is NULL before dereferencing it must return an error instead of triggering a synchronous exception at runtime in RELEASE builds.
Fixed in v4 already.
Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- case 2:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
PRODUCT_STRING_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetProduct (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- case 3:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
SERIAL_STRING_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- }
- break;
- default:
- DEBUG ((DEBUG_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value));
- break;
- }
- // Send the response
- if (ResponseData) {
- ASSERT (ResponseSize != 0);
ResponseSize is set explicitly by the switch statement above. Rather than ASSERTing that it went wrong, why not return an error from the default target? You could then also drop the "if (ResponseData)" test, and the "if (Descriptor)" test below.
Fixed in v4 already.
- if (Request->Length < ResponseSize) {
// Truncate response
ResponseSize = Request->Length;
- } else if (Request->Length > ResponseSize) {
DEBUG ((DEBUG_INFO, "USB: Info: ResponseSize < wLength\n"));
- }
- EpTx (0, ResponseData, ResponseSize);
- }
- if (Descriptor) {
Here.
Descriptor is only allocated when it's USB_DESC_TYPE_STRING. If drop Descriptor check at here, it'll cause error to execute FreePool().
- FreePool (Descriptor);
- }
- return EFI_SUCCESS;
+}
+STATIC +EFI_STATUS +HandleSetAddress (
- IN USB_DEVICE_REQUEST *Request
- )
+{
- // Pretty confused if bmRequestType is anything but this:
So is there any reason not to return an error?
Fixed in v4 already.
- ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE);
- DEBUG ((DEBUG_INFO, "USB: Setting address to %d\n", Request->Value));
- ResetEndpoints ();
- WRITE_REG32 (DCFG, (READ_REG32 (DCFG) & ~DCFG_DEVADDR_MASK) | DCFG_DEVADDR(Request->Value));
- EpTx (0, 0, 0);
What is the significance of transmitting 0 bytes of data? Probably this should be replaced by a macro. And that macro should use NULL, not 0, for the invalid pointer.
I don't know. Synoposys makes their spec as secret and they don't make any byte as public. I can only guess and guess.
- return EFI_SUCCESS;
+}
+STATIC +UINTN +UsbDrvRequestEndpoint (
- IN UINTN Type,
- IN UINTN Dir
- )
+{
- UINTN Ep = 1;
- UINTN Ret, NewBits;
- Ret = Ep | Dir;
- NewBits = (Type << 18) | 0x10000000;
No magic values, please. Replace with macro(s).
I don't like magic number too. But it's also secret to me.
- /*
- (Type << 18):Endpoint Type (EPType)
- 0x10000000:Endpoint Enable (EPEna)
- 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.
- (ep<<22):TxFIFO Number (TxFNum)
- 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.
- */
- if (Dir) { // IN: to host
- WRITE_REG32 (DIEPCTL (Ep), ((READ_REG32 (DIEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits | (Ep << 22) | DXEPCTL_NAKSTS);
- } else { // OUT: to device
- WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits);
More macros, please. There WRITE_REG32 lines are unreadable.
Fixed in v4 already.
- }
- return Ret;
+}
+STATIC +EFI_STATUS +HandleSetConfiguration (
- IN USB_DEVICE_REQUEST *Request
- )
+{
- ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE);
- // Cancel all transfers
- ResetEndpoints ();
- UsbDrvRequestEndpoint (2, 0);
- UsbDrvRequestEndpoint (2, 0x80);
No magic values, please.
Fixed in v4 already.
- WRITE_REG32 (DIEPCTL1, (READ_REG32 (DIEPCTL1)) | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11);
What is this operation doing? Please simplify with a temporary variable and some more descriptive #defines.
Fixed in v4 already.
- /* Enable interrupts on all endpoints */
- WRITE_REG32 (DAINTMSK, ~0);
- EpRx (1, CMD_SIZE);
The global variables also makes this code less readable.
- EpTx (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 = HandleGetDescriptor (Request);
- break;
- case USB_DEV_SET_ADDRESS:
- Status = HandleSetAddress (Request);
- break;
- case USB_DEV_SET_CONFIGURATION:
- Status = HandleSetConfiguration (Request);
- break;
- default:
- DEBUG ((DEBUG_ERROR,
"Didn't understand RequestType 0x%x Request 0x%x\n",
Request->RequestType, Request->Request));
Status = EFI_INVALID_PARAMETER;
- break;
- }
- return Status;
+}
+// Instead of actually registering interrupt handlers, we poll the controller's +// interrupt source register in this function. +STATIC +VOID +CheckInterrupts (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
+{
- UINT32 Ints, EpInts;
- // interrupt register
- Ints = READ_REG32 (GINTSTS);
- /*
- bus reset
- The core sets this bit to indicate that a reset is detected on the USB.
- */
- if (Ints & GINTSTS_USBRST) {
- WRITE_REG32 (DCFG, DCFG_DESCDMA | DCFG_NZ_STS_OUT_HSHK);
- ResetEndpoints ();
- }
- /*
- enumeration done, we now know the speed
- The core sets this bit to indicate that speed enumeration is complete. The
- application must read the Device Status (DSTS) register to obtain the
- enumerated speed.
- */
- if (Ints & GINTSTS_ENUMDONE) {
- /* Set up the maximum packet sizes accordingly */
- UINTN MaxPacket = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
A #define for that 64 please.
Fixed in v4 already.
- //Set Maximum In Packet Size (MPS)
- WRITE_REG32 (DIEPCTL1, ((READ_REG32 (DIEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
- //Set Maximum Out Packet Size (MPS)
- WRITE_REG32 (DOEPCTL1, ((READ_REG32 (DOEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
This seems to be a recurring pattern, so should there be a macro UPDATE_REG32 (Regname, Mask, Value) ?
Alternatively, please use a temporary variable to do the read separately.
Fixed in v4 already.
- }
- /*
- IN EP event
- The core sets this bit to indicate that an interrupt is pending on one of the IN
- endpoInts of the core (in Device mode). The application must read the
- Device All EndpoInts Interrupt (DAINT) register to determine the exact
- number of the IN endpoint on which the interrupt occurred, and then read
- the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to
- determine the exact cause of the interrupt. The application must clear the
- appropriate status bit in the corresponding DIEPINTn register to clear this bit.
- */
- if (Ints & GINTSTS_IEPINT) {
- EpInts = READ_REG32 (DIEPINT0);
- WRITE_REG32 (DIEPINT0, EpInts);
- if (EpInts & DXEPINT_XFERCOMPL) {
DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0)));
- }
- EpInts = READ_REG32 (DIEPINT1);
- WRITE_REG32 (DIEPINT1, EpInts);
- if (EpInts & DXEPINT_XFERCOMPL) {
DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n"));
- }
- }
Turn into helper function, please.
Fixed in v4 already.
- /*
- OUT EP event
- The core sets this bit to indicate that an interrupt is pending on one of the
- OUT endpoints of the core (in Device mode). The application must read the
- Device All EndpoInts Interrupt (DAINT) register to determine the exact
- number of the OUT endpoint on which the interrupt occurred, and then read
- the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register
- to determine the exact cause of the interrupt. The application must clear the
- appropriate status bit in the corresponding DOEPINTn register to clear this bit.
- */
- if (Ints & GINTSTS_OEPINT) {
- /* indicates the status of an endpoint
* with respect to USB- and AHB-related events. */
- EpInts = READ_REG32 (DOEPINT0);
- if (EpInts) {
WRITE_REG32 (DOEPINT0, EpInts);
if (EpInts & DXEPINT_XFERCOMPL) {
DEBUG ((DEBUG_INFO, "INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32 (DOEPTSIZ0)));
}
/*
*
IN Token Received When TxFIFO is Empty (INTknTXFEmp)
* Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
* was empty. This interrupt is asserted on the endpoint for which the IN token
* was received.
*/
if (EpInts & BIT3) { /* SETUP phase done */
WRITE_REG32 (DIEPCTL0, READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK);
WRITE_REG32 (DOEPCTL0, READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK);
/*clear IN EP intr*/
WRITE_REG32 (DIEPINT0, ~0);
HandleDeviceRequest((USB_DEVICE_REQUEST *)gCtrlReq);
}
/* Make sure EP0 OUT is set up to accept the next request */
WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));
/*
* IN Token Received When TxFIFO is Empty (INTknTXFEmp)
* Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
* was empty. This interrupt is asserted on the endpoint for which the IN token
* was received.
*/
gDmaDescEp0->status.b.bs = 0x3;
gDmaDescEp0->status.b.mtrf = 0;
gDmaDescEp0->status.b.sr = 0;
gDmaDescEp0->status.b.l = 1;
gDmaDescEp0->status.b.ioc = 1;
gDmaDescEp0->status.b.sp = 0;
gDmaDescEp0->status.b.bytes = 64;
gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
gDmaDescEp0->status.b.sts = 0;
gDmaDescEp0->status.b.bs = 0x0;
WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
// endpoint enable; clear NAK
WRITE_REG32 (DOEPCTL0, DXEPCTL_EPENA | DXEPCTL_CNAK);
- }
- EpInts = (READ_REG32 (DOEPINT1));
- if (EpInts) {
WRITE_REG32 (DOEPINT1, EpInts);
/* Transfer Completed Interrupt (XferCompl);Transfer completed */
if (EpInts & DXEPINT_XFERCOMPL) {
UINTN Bytes = RxDescBytes - gDmaDesc->status.b.bytes;
UINTN Len = 0;
ArmDataSynchronizationBarrier ();
if (MATCH_CMD_LITERAL ("download", RxBuf)) {
mNumDataBytes = AsciiStrHexToUint64 (RxBuf + sizeof ("download"));
} else {
if (mNumDataBytes != 0) {
mNumDataBytes -= Bytes;
}
}
mDataReceivedCallback (Bytes, RxBuf);
if (mNumDataBytes == 0) {
Len = CMD_SIZE;
} else if (mNumDataBytes > DATA_SIZE) {
Len = DATA_SIZE;
} else {
Len = mNumDataBytes;
}
EpRx (1, Len);
}
- }
- }
Turn into helper function, please.
Fixed in v4 already.
- //WRITE_REG32 clear ints
- WRITE_REG32 (GINTSTS, Ints);
+}
+EFI_STATUS +DwUsbSend (
- IN UINT8 EndpointIndex,
- IN UINTN Size,
- IN CONST VOID *Buffer
- )
+{
- EpTx (EndpointIndex, Buffer, Size);
- return EFI_SUCCESS;
+}
What is the purpose of this function?
Just want to use unified function name.
+STATIC +VOID +DwUsbInit (
- VOID
- )
+{
- VOID *Buf;
- UINT32 Data;
- Buf = UncachedAllocatePages (16);
No magic values, please.
Fixed in v4 already.
- gDmaDesc = Buf;
- gDmaDescEp0 = gDmaDesc + sizeof (dwc_otg_dev_dma_desc_t);
- gDmaDescIn = gDmaDescEp0 + sizeof (dwc_otg_dev_dma_desc_t);
- gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (dwc_otg_dev_dma_desc_t);
- ZeroMem (gDmaDesc, sizeof (dwc_otg_dev_dma_desc_t));
- ZeroMem (gDmaDescEp0, sizeof (dwc_otg_dev_dma_desc_t));
- ZeroMem (gDmaDescIn, sizeof (dwc_otg_dev_dma_desc_t));
Why not zero all of Buf once?
Fixed in v4 already.
- /*Reset usb controller.*/
- /* Wait for OTG AHB master idle */
- do {
- Data = READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE;
- } while (Data == 0);
- /* OTG: Assert Software Reset */
- WRITE_REG32 (GRSTCTL, GRSTCTL_CSFTRST);
- /* Wait for OTG to ack reset */
- while (READ_REG32 (GRSTCTL) & GRSTCTL_CSFTRST);
- /* Wait for OTG AHB master idle */
- while ((READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE) == 0);
Second use of an explicit loop on this in this function - and coded differently to the first one. Turn into a macro instead?
OK
- WRITE_REG32 (GDFIFOCFG, DATA_FIFO_CONFIG);
- WRITE_REG32 (GRXFSIZ, RX_SIZE);
- WRITE_REG32 (GNPTXFSIZ, ENDPOINT_TX_SIZE);
- WRITE_REG32 (DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);
- WRITE_REG32 (DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2);
- WRITE_REG32 (DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3);
- WRITE_REG32 (DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4);
- WRITE_REG32 (DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5);
- WRITE_REG32 (DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6);
- WRITE_REG32 (DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7);
- WRITE_REG32 (DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8);
- WRITE_REG32 (DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9);
- WRITE_REG32 (DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10);
- WRITE_REG32 (DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11);
- WRITE_REG32 (DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12);
- WRITE_REG32 (DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13);
- WRITE_REG32 (DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14);
- WRITE_REG32 (DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15);
- /*
- set Periodic TxFIFO Empty Level,
- Non-Periodic TxFIFO Empty Level,
- Enable DMA, Unmask Global Intr
- */
- WRITE_REG32 (GAHBCFG, GAHBCFG_CTRL_MASK);
- /*select 8bit UTMI+, ULPI Inerface*/
- WRITE_REG32 (GUSBCFG, 0x2400);
No magic numbers, please.
Fixed in v4 already.
- /* Detect usb work mode,host or device? */
- do {
- Data = READ_REG32 (GINTSTS);
- } while (Data & GINTSTS_CURMODE_HOST);
- MicroSecondDelay (3);
Why a delay? Why 3us? Is a barrier needed?
Fixed in v4 already.
- /*Init global and device mode csr register.*/
- /*set Non-Zero-Length status out handshake */
- Data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK;
No magic values, please.
It's also secret to me.
- WRITE_REG32 (DCFG, Data);
- /* Interrupt unmask: IN event, OUT event, bus reset */
(And enumeration complete?)
OK
- Data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE | GINTSTS_USBRST;
- WRITE_REG32 (GINTMSK, Data);
- do {
- Data = READ_REG32 (GINTSTS) & GINTSTS_ENUMDONE;
- } while (Data);
- /* Clear any pending OTG Interrupts */
- WRITE_REG32 (GOTGINT, ~0);
- /* Clear any pending interrupts */
- WRITE_REG32 (GINTSTS, ~0);
- WRITE_REG32 (GINTMSK, ~0);
- Data = READ_REG32 (GOTGINT);
- Data &= ~0x3000;
No magic values, please.
I don't know this too.
- WRITE_REG32 (GOTGINT, Data);
- /* endpoint settings cfg */
- ResetEndpoints ();
- MicroSecondDelay (1);
Why a delay? Why 1us? Is a barrier needed?
I think it's related to clock, not barrier. But I don't have the details.
- /* init finish. and ready to transfer data */
- /* Soft Disconnect */
- WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE | DCTL_SFTDISCON);
- MicroSecondDelay (10000);
Why a delay? Why 10ms? Is a barrier needed?
Nothing related to barrier. But it's black box to me.
- /* Soft Reconnect */
- WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE);
+}
+EFI_STATUS +EFIAPI +DwUsbStart (
- IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor,
- IN VOID **Descriptors,
- IN USB_DEVICE_RX_CALLBACK RxCallback,
- IN USB_DEVICE_TX_CALLBACK TxCallback
- )
+{
- UINT8 *Ptr;
- EFI_STATUS Status;
- EFI_EVENT TimerEvent;
- ASSERT (DeviceDescriptor != NULL);
- ASSERT (Descriptors[0] != NULL);
- ASSERT (RxCallback != NULL);
- ASSERT (TxCallback != NULL);
Can we do anything sane if any of these are NULL? If not, return error.
Fixed in v4 already.
- DwUsbInit();
- mDeviceDescriptor = DeviceDescriptor;
- mDescriptors = Descriptors[0];
- // Right now we just support one configuration
- ASSERT (mDeviceDescriptor->NumConfigurations == 1);
- mDeviceDescriptor->StrManufacturer = 1;
- mDeviceDescriptor->StrProduct = 2;
- mDeviceDescriptor->StrSerialNumber = 3;
No magic values, please. Presumably these are just indexes into a string table, but use #defines please.
Fixed in v4 already.
- // ... and one interface
- mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors;
- ASSERT (mConfigDescriptor->NumInterfaces == 1);
- Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR);
- mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr;
- Ptr += sizeof (USB_INTERFACE_DESCRIPTOR);
- mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr;
- mDataReceivedCallback = RxCallback;
- mDataSentCallback = TxCallback;
- // Register a timer event so CheckInterupts gets called periodically
- Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
CheckInterrupts,
NULL,
&TimerEvent
);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = gBS->SetTimer (
TimerEvent,
TimerPeriodic,
DW_INTERRUPT_POLL_PERIOD
);
- ASSERT_EFI_ERROR (Status);
- return Status;
+}
+USB_DEVICE_PROTOCOL mUsbDevice = {
- DwUsbStart,
- DwUsbSend
+};
+EFI_STATUS +EFIAPI +DwUsbEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
+{
- EFI_STATUS Status;
- Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = DwUsb->PhyInit(USB_DEVICE_MODE);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- return gBS->InstallProtocolInterface (
&ImageHandle,
&gUsbDeviceProtocolGuid,
EFI_NATIVE_INTERFACE,
&mUsbDevice
);
+} diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec new file mode 100644 index 0000000..f991492 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec @@ -0,0 +1,46 @@ +#/** @file +# Framework Module Development Environment Industry Standards +# +# This Package provides headers and libraries that conform to EFI/PI Industry standards. +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR> +# Copyright (c) 2015-2017, Linaro. All rights reserved.<BR> +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/
+[Defines]
- DEC_SPECIFICATION = 0x00010019
- PACKAGE_NAME = OpenPlatformDriversUsbDwUsbDxePkg
I think DwUsbDxePkg would be sufficient.
Fixed in v4 already.
- PACKAGE_GUID = 114a3be9-10f7-4bf1-81ca-09ac52d4c3d5
- PACKAGE_VERSION = 0.1
+################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################
+[Guids.common]
- gAndroidFastbootUsbGuid = { 0xf6bec3fe, 0x88fb, 0x11e3, { 0xae, 0x84, 0xe7, 0x3b, 0x77, 0x56, 0x1c, 0x35 }}
Is this included only for the DEPEX? This does not feel like the right way of doing this.
Fixed in v4 already.
- gDwUsbDxeTokenSpaceGuid = { 0x131c4d02, 0x9449, 0x4ee9, { 0xba, 0x3d, 0x69, 0x50, 0x21, 0x89, 0x26, 0x0b }}
+[Protocols.common]
- gDwUsbProtocolGuid = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
+[PcdsFixedAtBuild.common]
- # DwUsb Driver PCDs
- gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0x0|UINT32|0x00000001
- gDwUsbDxeTokenSpaceGuid.PcdSysCtrlBaseAddress|0x0|UINT32|0x00000002
I am really not happy about adding additional drivers with hard-coded base addresses. Especially not ones that claim to be DXE/UEFI drivers.
But I realy don't know how to make it as dynamic.
+/**
- DMA Descriptor structure
- DMA Descriptor structure contains two quadlets:
- Status quadlet and Data buffer pointer.
- */
+typedef struct {
- /** DMA Descriptor status quadlet */
- dev_dma_desc_sts_t status;
- /** DMA Descriptor data buffer pointer */
- UINT32 buf;
+} dwc_otg_dev_dma_desc_t;
The above union and struct do not conform to EDK2 coding style.
Fixed in v4 already.
+#endif //ifndef __DW_USB_DXE_H__ diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf new file mode 100644 index 0000000..fc1e988 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf @@ -0,0 +1,52 @@ +#/** @file +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/
+[Defines]
- INF_VERSION = 0x00010019
- BASE_NAME = DwUsbDxe
- FILE_GUID = 72d78ea6-4dee-11e3-8100-f3842a48d0a0
- MODULE_TYPE = UEFI_DRIVER
I don't believe the driver in its current state can be called a UEFI_DRIVER. Combined with the ordering issue, should this be a DXE_DRIVER instead?
It'll be called by App. When App is running, DXE driver should end its life cycle. Is it right?
- VERSION_STRING = 1.0
- ENTRY_POINT = DwUsbEntryPoint
+[Sources.common]
- DwUsbDxe.c
+[LibraryClasses]
- ArmLib
- DebugLib
- IoLib
- MemoryAllocationLib
- TimerLib
- UefiBootServicesTableLib
- UefiDriverEntryPoint
- UncachedMemoryAllocationLib
- CacheMaintenanceLib
Please sort LibraryClasses.
Fixed in v4 already.
+[Protocols]
- gEfiDriverBindingProtocolGuid
- gUsbDeviceProtocolGuid
+[Packages]
- ArmPkg/ArmPkg.dec
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- EmbeddedPkg/EmbeddedPkg.dec
- OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
Please sort Packages.
Fixed in v4 already.
/ Leif
On 4 February 2017 at 05:13, Haojian Zhuang haojian.zhuang@linaro.org wrote:
Support Designware USB controller.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org
Drivers/Usb/DwUsbDxe/DwUsbDxe.c | 796 ++++++++++++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.dec | 46 +++ Drivers/Usb/DwUsbDxe/DwUsbDxe.h | 627 ++++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.inf | 52 +++ Include/Protocol/DwUsb.h | 81 ++++ 5 files changed, 1602 insertions(+) create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.c create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.dec create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.h create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.inf create mode 100644 Include/Protocol/DwUsb.h
diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.c b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c new file mode 100644 index 0000000..bdd8405 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c @@ -0,0 +1,796 @@ +/** @file
- Copyright (c) 2015-2017, Linaro. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <IndustryStandard/Usb.h> +#include <Library/ArmLib.h> +#include <Library/TimerLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UncachedMemoryAllocationLib.h> +#include <Library/CacheMaintenanceLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/BaseLib.h> +#include <Protocol/DwUsb.h> +#include <Protocol/UsbDevice.h>
+#include "DwUsbDxe.h"
+#define USB_TYPE_LENGTH 16 +#define USB_BLOCK_HIGH_SPEED_SIZE 512 +#define DATA_SIZE 32768 +#define CMD_SIZE 512 +#define MATCH_CMD_LITERAL(Cmd, Buf) !AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)
+// The time between interrupt polls, in units of 100 nanoseconds +// 10 Microseconds +#define DW_INTERRUPT_POLL_PERIOD 10000
+EFI_GUID gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID;
+STATIC dwc_otg_dev_dma_desc_t *gDmaDesc,*gDmaDescEp0,*gDmaDescIn; +STATIC USB_DEVICE_REQUEST *gCtrlReq; +STATIC VOID *RxBuf; +STATIC UINTN RxDescBytes = 0; +STATIC UINTN mNumDataBytes;
+STATIC DW_USB_PROTOCOL *DwUsb;
+STATIC USB_DEVICE_DESCRIPTOR *mDeviceDescriptor;
+// The config descriptor, interface descriptor, and endpoint descriptors in 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;
+/* To detect which mode was run, high speed or full speed */ +STATIC +UINTN +UsbDrvPortSpeed (
- VOID
- )
+{
- /*
- 2'b00: High speed (PHY clock is running at 30 or 60 MHz)
- */
- UINT32 Val = READ_REG32 (DSTS) & 2;
- return (!Val);
+}
+STATIC +VOID +ResetEndpoints (
- VOID
- )
+{
- /* EP0 IN ACTIVE NEXT=1 */
- WRITE_REG32 (DIEPCTL0, DXEPCTL_USBACTEP | BIT11);
- /* EP0 OUT ACTIVE */
- WRITE_REG32 (DOEPCTL0, DXEPCTL_USBACTEP);
- /* Clear any pending OTG Interrupts */
- WRITE_REG32 (GOTGINT, ~0);
- /* Clear any pending interrupts */
- WRITE_REG32 (GINTSTS, ~0);
- WRITE_REG32 (DIEPINT0, ~0);
- WRITE_REG32 (DOEPINT0, ~0);
- WRITE_REG32 (DIEPINT1, ~0);
- WRITE_REG32 (DOEPINT1, ~0);
- /* IN EP interrupt mask */
- WRITE_REG32 (DIEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);
- /* OUT EP interrupt mask */
- WRITE_REG32 (DOEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK);
- /* Enable interrupts on Ep0 */
- WRITE_REG32 (DAINTMSK, (1 << DAINTMSK_OUTEPMSK_SHIFT) | (1 << DAINTMSK_INEPMSK_SHIFT));
- /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/
- WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));
- //notes that:the compulsive conversion is expectable.
- gDmaDescEp0->status.b.bs = 0x3;
- gDmaDescEp0->status.b.mtrf = 0;
- gDmaDescEp0->status.b.sr = 0;
- gDmaDescEp0->status.b.l = 1;
- gDmaDescEp0->status.b.ioc = 1;
- gDmaDescEp0->status.b.sp = 0;
- gDmaDescEp0->status.b.bytes = 64;
- gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
- gDmaDescEp0->status.b.sts = 0;
- gDmaDescEp0->status.b.bs = 0x0;
- WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
- /* EP0 OUT ENABLE CLEARNAK */
- WRITE_REG32 (DOEPCTL0, (READ_REG32 (DOEPCTL0) | DXEPCTL_EPENA | DXEPCTL_CNAK));
+}
+STATIC +VOID +EpTx (
- IN UINT8 Ep,
- IN CONST VOID *Ptr,
- IN UINTN Len
- )
+{
- UINT32 BlockSize;
- UINT32 Packets;
- /* EPx OUT ACTIVE */
- WRITE_REG32 (DIEPCTL (Ep), (READ_REG32 (DIEPCTL (Ep))) | DXEPCTL_USBACTEP);
- if (!Ep) {
BlockSize = 64;
- } else {
BlockSize = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
- }
- Packets = (Len + BlockSize - 1) / BlockSize;
- if (!Len) {
/* send one empty packet */
gDmaDescIn->status.b.bs = 0x3;
gDmaDescIn->status.b.l = 1;
gDmaDescIn->status.b.ioc = 1;
gDmaDescIn->status.b.sp = 1;
gDmaDescIn->status.b.bytes = 0;
gDmaDescIn->buf = 0;
gDmaDescIn->status.b.sts = 0;
gDmaDescIn->status.b.bs = 0x0;
WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn)); // DMA Address (DMAAddr) is zero
- } else {
WRITE_REG32 (DIEPTSIZ (Ep), Len | (Packets << 19));
//flush cache
WriteBackDataCacheRange ((VOID *)Ptr, Len);
gDmaDescIn->status.b.bs = 0x3;
gDmaDescIn->status.b.l = 1;
gDmaDescIn->status.b.ioc = 1;
gDmaDescIn->status.b.sp = 1;
gDmaDescIn->status.b.bytes = Len;
gDmaDescIn->buf = (UINT32)((UINTN)Ptr);
gDmaDescIn->status.b.sts = 0;
gDmaDescIn->status.b.bs = 0x0;
WRITE_REG32 (DIEPDMA (Ep), (UINT32)(UINTN)(gDmaDescIn)); // Ptr is DMA address
- }
- ArmDataSynchronizationBarrier ();
- /* epena & cnak */
- WRITE_REG32 (DIEPCTL (Ep), READ_REG32 (DIEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11);
+}
+STATIC +VOID +EpRx (
- IN UINTN Ep,
- IN UINTN Len
- )
+{
- /* EPx UNSTALL */
- WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & (~DXEPCTL_STALL)));
- /* EPx OUT ACTIVE */
- WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_USBACTEP));
- if (Len >= DATA_SIZE) {
- RxDescBytes = DATA_SIZE;
- } else {
- RxDescBytes = Len;
- }
- RxBuf = AllocatePool (DATA_SIZE);
- ASSERT (RxBuf != NULL);
- InvalidateDataCacheRange (RxBuf, Len);
- gDmaDesc->status.b.bs = 0x3;
- gDmaDesc->status.b.mtrf = 0;
- gDmaDesc->status.b.sr = 0;
- gDmaDesc->status.b.l = 1;
- gDmaDesc->status.b.ioc = 1;
- gDmaDesc->status.b.sp = 0;
- gDmaDesc->status.b.bytes = (UINT32)RxDescBytes;
- gDmaDesc->buf = (UINT32)((UINTN)RxBuf);
- gDmaDesc->status.b.sts = 0;
- gDmaDesc->status.b.bs = 0x0;
- ArmDataSynchronizationBarrier ();
- WRITE_REG32 (DOEPDMA (Ep), (UINT32)((UINTN)gDmaDesc));
- /* EPx OUT ENABLE CLEARNAK */
- WRITE_REG32 (DOEPCTL (Ep), (READ_REG32 (DOEPCTL (Ep)) | DXEPCTL_EPENA | DXEPCTL_CNAK));
+}
+STATIC +EFI_STATUS +HandleGetDescriptor (
- IN USB_DEVICE_REQUEST *Request
- )
+{
- UINT8 DescriptorType;
- UINTN ResponseSize;
- VOID *ResponseData;
- EFI_USB_STRING_DESCRIPTOR *Descriptor = NULL;
- UINTN DescriptorSize;
- ResponseSize = 0;
- ResponseData = NULL;
- // Pretty confused if bmRequestType is anything but this:
- ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE);
- // Choose the response
- DescriptorType = Request->Value >> 8;
- switch (DescriptorType) {
- case USB_DESC_TYPE_DEVICE:
- DEBUG ((DEBUG_INFO, "USB: Got a request for device descriptor\n"));
- ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR);
- ResponseData = mDeviceDescriptor;
- break;
- case USB_DESC_TYPE_CONFIG:
- DEBUG ((DEBUG_INFO, "USB: Got a request for config descriptor\n"));
- ResponseSize = mConfigDescriptor->TotalLength;
- ResponseData = mDescriptors;
- break;
- case USB_DESC_TYPE_STRING:
- DEBUG ((DEBUG_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF));
- switch (Request->Value & 0xff) {
- case 0:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
LANG_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
Descriptor->Length = LANG_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetLang (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- case 1:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- case 2:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
PRODUCT_STRING_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetProduct (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- case 3:
DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) +
SERIAL_STRING_LENGTH * sizeof (CHAR16) + 1;
Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize);
ASSERT (Descriptor != NULL);
Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16);
Descriptor->DescriptorType = USB_DESC_TYPE_STRING;
DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length);
ResponseSize = Descriptor->Length;
ResponseData = Descriptor;
break;
- }
- break;
- default:
- DEBUG ((DEBUG_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value));
- break;
- }
- // Send the response
- if (ResponseData) {
- ASSERT (ResponseSize != 0);
- if (Request->Length < ResponseSize) {
// Truncate response
ResponseSize = Request->Length;
- } else if (Request->Length > ResponseSize) {
DEBUG ((DEBUG_INFO, "USB: Info: ResponseSize < wLength\n"));
- }
- EpTx (0, ResponseData, ResponseSize);
- }
- if (Descriptor) {
- FreePool (Descriptor);
- }
- return EFI_SUCCESS;
+}
+STATIC +EFI_STATUS +HandleSetAddress (
- IN USB_DEVICE_REQUEST *Request
- )
+{
- // Pretty confused if bmRequestType is anything but this:
- ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE);
- DEBUG ((DEBUG_INFO, "USB: Setting address to %d\n", Request->Value));
- ResetEndpoints ();
- WRITE_REG32 (DCFG, (READ_REG32 (DCFG) & ~DCFG_DEVADDR_MASK) | DCFG_DEVADDR(Request->Value));
- EpTx (0, 0, 0);
- return EFI_SUCCESS;
+}
+STATIC +UINTN +UsbDrvRequestEndpoint (
- IN UINTN Type,
- IN UINTN Dir
- )
+{
- UINTN Ep = 1;
- UINTN Ret, NewBits;
- Ret = Ep | Dir;
- NewBits = (Type << 18) | 0x10000000;
- /*
- (Type << 18):Endpoint Type (EPType)
- 0x10000000:Endpoint Enable (EPEna)
- 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.
- (ep<<22):TxFIFO Number (TxFNum)
- 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.
- */
- if (Dir) { // IN: to host
- WRITE_REG32 (DIEPCTL (Ep), ((READ_REG32 (DIEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits | (Ep << 22) | DXEPCTL_NAKSTS);
- } else { // OUT: to device
- WRITE_REG32 (DOEPCTL (Ep), ((READ_REG32 (DOEPCTL (Ep))) & ~DXEPCTL_EPTYPE_MASK) | NewBits);
- }
- return Ret;
+}
+STATIC +EFI_STATUS +HandleSetConfiguration (
- IN USB_DEVICE_REQUEST *Request
- )
+{
- ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE);
- // Cancel all transfers
- ResetEndpoints ();
- UsbDrvRequestEndpoint (2, 0);
- UsbDrvRequestEndpoint (2, 0x80);
- WRITE_REG32 (DIEPCTL1, (READ_REG32 (DIEPCTL1)) | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11);
- /* Enable interrupts on all endpoints */
- WRITE_REG32 (DAINTMSK, ~0);
- EpRx (1, CMD_SIZE);
- EpTx (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 = HandleGetDescriptor (Request);
- break;
- case USB_DEV_SET_ADDRESS:
- Status = HandleSetAddress (Request);
- break;
- case USB_DEV_SET_CONFIGURATION:
- Status = HandleSetConfiguration (Request);
- break;
- default:
- DEBUG ((DEBUG_ERROR,
"Didn't understand RequestType 0x%x Request 0x%x\n",
Request->RequestType, Request->Request));
Status = EFI_INVALID_PARAMETER;
- break;
- }
- return Status;
+}
+// Instead of actually registering interrupt handlers, we poll the controller's +// interrupt source register in this function. +STATIC +VOID +CheckInterrupts (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
+{
- UINT32 Ints, EpInts;
- // interrupt register
- Ints = READ_REG32 (GINTSTS);
- /*
- bus reset
- The core sets this bit to indicate that a reset is detected on the USB.
- */
- if (Ints & GINTSTS_USBRST) {
- WRITE_REG32 (DCFG, DCFG_DESCDMA | DCFG_NZ_STS_OUT_HSHK);
- ResetEndpoints ();
- }
- /*
- enumeration done, we now know the speed
- The core sets this bit to indicate that speed enumeration is complete. The
- application must read the Device Status (DSTS) register to obtain the
- enumerated speed.
- */
- if (Ints & GINTSTS_ENUMDONE) {
- /* Set up the maximum packet sizes accordingly */
- UINTN MaxPacket = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
- //Set Maximum In Packet Size (MPS)
- WRITE_REG32 (DIEPCTL1, ((READ_REG32 (DIEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
- //Set Maximum Out Packet Size (MPS)
- WRITE_REG32 (DOEPCTL1, ((READ_REG32 (DOEPCTL1)) & ~DXEPCTL_MPS_MASK) | MaxPacket);
- }
- /*
- IN EP event
- The core sets this bit to indicate that an interrupt is pending on one of the IN
- endpoInts of the core (in Device mode). The application must read the
- Device All EndpoInts Interrupt (DAINT) register to determine the exact
- number of the IN endpoint on which the interrupt occurred, and then read
- the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to
- determine the exact cause of the interrupt. The application must clear the
- appropriate status bit in the corresponding DIEPINTn register to clear this bit.
- */
- if (Ints & GINTSTS_IEPINT) {
- EpInts = READ_REG32 (DIEPINT0);
- WRITE_REG32 (DIEPINT0, EpInts);
- if (EpInts & DXEPINT_XFERCOMPL) {
DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0)));
- }
- EpInts = READ_REG32 (DIEPINT1);
- WRITE_REG32 (DIEPINT1, EpInts);
- if (EpInts & DXEPINT_XFERCOMPL) {
DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n"));
- }
- }
- /*
- OUT EP event
- The core sets this bit to indicate that an interrupt is pending on one of the
- OUT endpoints of the core (in Device mode). The application must read the
- Device All EndpoInts Interrupt (DAINT) register to determine the exact
- number of the OUT endpoint on which the interrupt occurred, and then read
- the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register
- to determine the exact cause of the interrupt. The application must clear the
- appropriate status bit in the corresponding DOEPINTn register to clear this bit.
- */
- if (Ints & GINTSTS_OEPINT) {
- /* indicates the status of an endpoint
* with respect to USB- and AHB-related events. */
- EpInts = READ_REG32 (DOEPINT0);
- if (EpInts) {
WRITE_REG32 (DOEPINT0, EpInts);
if (EpInts & DXEPINT_XFERCOMPL) {
DEBUG ((DEBUG_INFO, "INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32 (DOEPTSIZ0)));
}
/*
*
IN Token Received When TxFIFO is Empty (INTknTXFEmp)
* Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
* was empty. This interrupt is asserted on the endpoint for which the IN token
* was received.
*/
if (EpInts & BIT3) { /* SETUP phase done */
WRITE_REG32 (DIEPCTL0, READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK);
WRITE_REG32 (DOEPCTL0, READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK);
/*clear IN EP intr*/
WRITE_REG32 (DIEPINT0, ~0);
HandleDeviceRequest((USB_DEVICE_REQUEST *)gCtrlReq);
}
/* Make sure EP0 OUT is set up to accept the next request */
WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64));
/*
* IN Token Received When TxFIFO is Empty (INTknTXFEmp)
* Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
* was empty. This interrupt is asserted on the endpoint for which the IN token
* was received.
*/
gDmaDescEp0->status.b.bs = 0x3;
gDmaDescEp0->status.b.mtrf = 0;
gDmaDescEp0->status.b.sr = 0;
gDmaDescEp0->status.b.l = 1;
gDmaDescEp0->status.b.ioc = 1;
gDmaDescEp0->status.b.sp = 0;
gDmaDescEp0->status.b.bytes = 64;
gDmaDescEp0->buf = (UINT32)(UINTN)(gCtrlReq);
gDmaDescEp0->status.b.sts = 0;
gDmaDescEp0->status.b.bs = 0x0;
WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)(gDmaDescEp0));
// endpoint enable; clear NAK
WRITE_REG32 (DOEPCTL0, DXEPCTL_EPENA | DXEPCTL_CNAK);
- }
- EpInts = (READ_REG32 (DOEPINT1));
- if (EpInts) {
WRITE_REG32 (DOEPINT1, EpInts);
/* Transfer Completed Interrupt (XferCompl);Transfer completed */
if (EpInts & DXEPINT_XFERCOMPL) {
UINTN Bytes = RxDescBytes - gDmaDesc->status.b.bytes;
UINTN Len = 0;
ArmDataSynchronizationBarrier ();
if (MATCH_CMD_LITERAL ("download", RxBuf)) {
mNumDataBytes = AsciiStrHexToUint64 (RxBuf + sizeof ("download"));
} else {
if (mNumDataBytes != 0) {
mNumDataBytes -= Bytes;
}
}
mDataReceivedCallback (Bytes, RxBuf);
if (mNumDataBytes == 0) {
Len = CMD_SIZE;
} else if (mNumDataBytes > DATA_SIZE) {
Len = DATA_SIZE;
} else {
Len = mNumDataBytes;
}
EpRx (1, Len);
}
- }
- }
- //WRITE_REG32 clear ints
- WRITE_REG32 (GINTSTS, Ints);
+}
+EFI_STATUS +DwUsbSend (
- IN UINT8 EndpointIndex,
- IN UINTN Size,
- IN CONST VOID *Buffer
- )
+{
- EpTx (EndpointIndex, Buffer, Size);
- return EFI_SUCCESS;
+}
+STATIC +VOID +DwUsbInit (
- VOID
- )
+{
- VOID *Buf;
- UINT32 Data;
- Buf = UncachedAllocatePages (16);
- gDmaDesc = Buf;
- gDmaDescEp0 = gDmaDesc + sizeof (dwc_otg_dev_dma_desc_t);
- gDmaDescIn = gDmaDescEp0 + sizeof (dwc_otg_dev_dma_desc_t);
- gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (dwc_otg_dev_dma_desc_t);
- ZeroMem (gDmaDesc, sizeof (dwc_otg_dev_dma_desc_t));
- ZeroMem (gDmaDescEp0, sizeof (dwc_otg_dev_dma_desc_t));
- ZeroMem (gDmaDescIn, sizeof (dwc_otg_dev_dma_desc_t));
- /*Reset usb controller.*/
- /* Wait for OTG AHB master idle */
- do {
- Data = READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE;
- } while (Data == 0);
- /* OTG: Assert Software Reset */
- WRITE_REG32 (GRSTCTL, GRSTCTL_CSFTRST);
- /* Wait for OTG to ack reset */
- while (READ_REG32 (GRSTCTL) & GRSTCTL_CSFTRST);
- /* Wait for OTG AHB master idle */
- while ((READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE) == 0);
- WRITE_REG32 (GDFIFOCFG, DATA_FIFO_CONFIG);
- WRITE_REG32 (GRXFSIZ, RX_SIZE);
- WRITE_REG32 (GNPTXFSIZ, ENDPOINT_TX_SIZE);
- WRITE_REG32 (DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);
- WRITE_REG32 (DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2);
- WRITE_REG32 (DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3);
- WRITE_REG32 (DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4);
- WRITE_REG32 (DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5);
- WRITE_REG32 (DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6);
- WRITE_REG32 (DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7);
- WRITE_REG32 (DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8);
- WRITE_REG32 (DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9);
- WRITE_REG32 (DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10);
- WRITE_REG32 (DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11);
- WRITE_REG32 (DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12);
- WRITE_REG32 (DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13);
- WRITE_REG32 (DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14);
- WRITE_REG32 (DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15);
- /*
- set Periodic TxFIFO Empty Level,
- Non-Periodic TxFIFO Empty Level,
- Enable DMA, Unmask Global Intr
- */
- WRITE_REG32 (GAHBCFG, GAHBCFG_CTRL_MASK);
- /*select 8bit UTMI+, ULPI Inerface*/
- WRITE_REG32 (GUSBCFG, 0x2400);
- /* Detect usb work mode,host or device? */
- do {
- Data = READ_REG32 (GINTSTS);
- } while (Data & GINTSTS_CURMODE_HOST);
- MicroSecondDelay (3);
- /*Init global and device mode csr register.*/
- /*set Non-Zero-Length status out handshake */
- Data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK;
- WRITE_REG32 (DCFG, Data);
- /* Interrupt unmask: IN event, OUT event, bus reset */
- Data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE | GINTSTS_USBRST;
- WRITE_REG32 (GINTMSK, Data);
- do {
- Data = READ_REG32 (GINTSTS) & GINTSTS_ENUMDONE;
- } while (Data);
- /* Clear any pending OTG Interrupts */
- WRITE_REG32 (GOTGINT, ~0);
- /* Clear any pending interrupts */
- WRITE_REG32 (GINTSTS, ~0);
- WRITE_REG32 (GINTMSK, ~0);
- Data = READ_REG32 (GOTGINT);
- Data &= ~0x3000;
- WRITE_REG32 (GOTGINT, Data);
- /* endpoint settings cfg */
- ResetEndpoints ();
- MicroSecondDelay (1);
- /* init finish. and ready to transfer data */
- /* Soft Disconnect */
- WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE | DCTL_SFTDISCON);
- MicroSecondDelay (10000);
- /* Soft Reconnect */
- WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE);
+}
+EFI_STATUS +EFIAPI +DwUsbStart (
- IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor,
- IN VOID **Descriptors,
- IN USB_DEVICE_RX_CALLBACK RxCallback,
- IN USB_DEVICE_TX_CALLBACK TxCallback
- )
+{
- UINT8 *Ptr;
- EFI_STATUS Status;
- EFI_EVENT TimerEvent;
- ASSERT (DeviceDescriptor != NULL);
- ASSERT (Descriptors[0] != NULL);
- ASSERT (RxCallback != NULL);
- ASSERT (TxCallback != NULL);
- DwUsbInit();
- mDeviceDescriptor = DeviceDescriptor;
- mDescriptors = Descriptors[0];
- // Right now we just support one configuration
- ASSERT (mDeviceDescriptor->NumConfigurations == 1);
- mDeviceDescriptor->StrManufacturer = 1;
- mDeviceDescriptor->StrProduct = 2;
- mDeviceDescriptor->StrSerialNumber = 3;
- // ... and one interface
- mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors;
- ASSERT (mConfigDescriptor->NumInterfaces == 1);
- Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR);
- mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr;
- Ptr += sizeof (USB_INTERFACE_DESCRIPTOR);
- mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr;
- mDataReceivedCallback = RxCallback;
- mDataSentCallback = TxCallback;
- // Register a timer event so CheckInterupts gets called periodically
- Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
CheckInterrupts,
NULL,
&TimerEvent
);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = gBS->SetTimer (
TimerEvent,
TimerPeriodic,
DW_INTERRUPT_POLL_PERIOD
);
- ASSERT_EFI_ERROR (Status);
- return Status;
+}
+USB_DEVICE_PROTOCOL mUsbDevice = {
- DwUsbStart,
- DwUsbSend
+};
+EFI_STATUS +EFIAPI +DwUsbEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
+{
- EFI_STATUS Status;
- Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = DwUsb->PhyInit(USB_DEVICE_MODE);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- return gBS->InstallProtocolInterface (
&ImageHandle,
&gUsbDeviceProtocolGuid,
EFI_NATIVE_INTERFACE,
&mUsbDevice
);
+} diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec new file mode 100644 index 0000000..f991492 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec @@ -0,0 +1,46 @@ +#/** @file +# Framework Module Development Environment Industry Standards +# +# This Package provides headers and libraries that conform to EFI/PI Industry standards. +# Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.<BR> +# Copyright (c) 2015-2017, Linaro. All rights reserved.<BR> +# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/
+[Defines]
- DEC_SPECIFICATION = 0x00010019
- PACKAGE_NAME = OpenPlatformDriversUsbDwUsbDxePkg
- PACKAGE_GUID = 114a3be9-10f7-4bf1-81ca-09ac52d4c3d5
- PACKAGE_VERSION = 0.1
+################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################
+[Guids.common]
- gAndroidFastbootUsbGuid = { 0xf6bec3fe, 0x88fb, 0x11e3, { 0xae, 0x84, 0xe7, 0x3b, 0x77, 0x56, 0x1c, 0x35 }}
- gDwUsbDxeTokenSpaceGuid = { 0x131c4d02, 0x9449, 0x4ee9, { 0xba, 0x3d, 0x69, 0x50, 0x21, 0x89, 0x26, 0x0b }}
+[Protocols.common]
- gDwUsbProtocolGuid = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
+[PcdsFixedAtBuild.common]
- # DwUsb Driver PCDs
- gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0x0|UINT32|0x00000001
- gDwUsbDxeTokenSpaceGuid.PcdSysCtrlBaseAddress|0x0|UINT32|0x00000002
diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.h b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h new file mode 100644 index 0000000..7f909c3 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h @@ -0,0 +1,627 @@ +/** @file
- Copyright (c) 2015-2017, Linaro. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef __DW_USB_DXE_H__ +#define __DW_USB_DXE_H__
+#define DW_USB_BASE FixedPcdGet32 (PcdDwUsbDxeBaseAddress)
+#define READ_REG32(Offset) MmioRead32 (DW_USB_BASE + Offset) +#define READ_REG16(Offset) (UINT16)READ_REG32 (Offset) +#define WRITE_REG32(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, Val) +#define WRITE_REG16(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val) +#define WRITE_REG8(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val)
+// Max packet size in bytes (For Full Speed USB 64 is the only valid value) +#define MAX_PACKET_SIZE_CONTROL 64
+#define MAX_PACKET_SIZE_BULK 512
+// 8 Endpoints, in and out. Don't count the Endpoint 0 setup buffer +#define DW_NUM_ENDPOINTS 16
+// Endpoint Indexes +#define DW_EP0SETUP 0x20 +#define DW_EP0RX 0x00 +#define DW_EP0TX 0x01 +#define DW_EP1RX 0x02 +#define DW_EP1TX 0x03
+// DcInterrupt bits +#define DW_DC_INTERRUPT_EP1TX BIT13 +#define DW_DC_INTERRUPT_EP1RX BIT12 +#define DW_DC_INTERRUPT_EP0TX BIT11 +#define DW_DC_INTERRUPT_EP0RX BIT10 +#define DW_DC_INTERRUPT_EP0SETUP BIT8 +#define DW_DC_INTERRUPT_VBUS BIT7 +#define DW_DC_INTERRUPT_DMA BIT6 +#define DW_DC_INTERRUPT_HS_STAT BIT5 +#define DW_DC_INTERRUPT_RESUME BIT4 +#define DW_DC_INTERRUPT_SUSP BIT3 +#define DW_DC_INTERRUPT_PSOF BIT2 +#define DW_DC_INTERRUPT_SOF BIT1 +#define DW_DC_INTERRUPT_BRESET BIT0 +// All valid peripheral controller int rrupts +#define DW_DC_INTERRUPT_MASK 0x003FFFDFF
+#define DW_ADDRESS 0x200 +#define DW_ADDRESS_DEVEN BIT7
+#define DW_MODE 0x20C +#define DW_MODE_DATA_BUS_WIDTH BIT8 +#define DW_MODE_CLKAON BIT7 +#define DW_MODE_SFRESET BIT4 +#define DW_MODE_WKUPCS BIT2
+#define DW_ENDPOINT_MAX_PACKET_SIZE 0x204
+#define DW_ENDPOINT_TYPE 0x208 +#define DW_ENDPOINT_TYPE_NOEMPKT BIT4 +#define DW_ENDPOINT_TYPE_ENABLE BIT3
+#define DW_INTERRUPT_CONFIG 0x210 +// Interrupt config value to only interrupt on ACK of IN and OUT tokens +#define DW_INTERRUPT_CONFIG_ACK_ONLY (BIT2 | BIT5 | BIT6)
+#define DW_DC_INTERRUPT 0x218 +#define DW_DC_INTERRUPT_ENABLE 0x214
+#define DW_CTRL_FUNCTION 0x228 +#define DW_CTRL_FUNCTION_VENDP BIT3 +#define DW_CTRL_FUNCTION_DSEN BIT2 +#define DW_CTRL_FUNCTION_STATUS BIT1
+#define DW_DEVICE_UNLOCK 0x27C +#define DW_DEVICE_UNLOCK_MAGIC 0xAA37
+#define DW_SW_RESET_REG 0x30C +#define DW_SW_RESET_ALL BIT0
+#define DW_DEVICE_ID 0x370
+#define DW_OTG_CTRL_SET 0x374 +#define DW_OTG_CTRL_CLR (OTG_CTRL_SET + 2) +#define DW_OTG_CTRL_OTG_DISABLE BIT10 +#define DW_OTG_CTRL_VBUS_CHRG BIT6 +#define DW_OTG_CTRL_VBUS_DISCHRG BIT5 +#define DW_OTG_CTRL_DM_PULLDOWN BIT2 +#define DW_OTG_CTRL_DP_PULLDOWN BIT1 +#define DW_OTG_CTRL_DP_PULLUP BIT0
+#define DW_OTG_STATUS 0x378 +#define DW_OTG_STATUS_B_SESS_END BIT7 +#define DW_OTG_STATUS_A_B_SESS_VLD BIT1
+#define DW_OTG_INTERRUPT_LATCH_SET 0x37C +#define DW_OTG_INTERRUPT_LATCH_CLR 0x37E +#define DW_OTG_INTERRUPT_ENABLE_RISE 0x384
+#define DW_DMA_ENDPOINT_INDEX 0x258
+#define DW_ENDPOINT_INDEX 0x22c +#define DW_DATA_PORT 0x220 +#define DW_BUFFER_LENGTH 0x21c
+// Device ID Values +#define PHILLIPS_VENDOR_ID_VAL 0x04cc +#define DW_PRODUCT_ID_VAL 0x1761 +#define DW_DEVICE_ID_VAL ((ISP1761_PRODUCT_ID_VAL << 16) | \
PHILLIPS_VENDOR_ID_VAL)
+#define DWC_OTG_BASE DW_USB_BASE
+#define USB_NUM_ENDPOINTS 2 +#define MAX_EPS_CHANNELS 16
+#define BULK_OUT_EP 1 +#define BULK_IN_EP 1
+#define RX_REQ_LEN 512 +#define MAX_PACKET_LEN 512
+#define DATA_FIFO_CONFIG 0x0F801000 +/* RX FIFO: 2048 bytes */ +#define RX_SIZE 0x00000200 +/* Non-periodic TX FIFO: 128 bytes. start address: 0x200 * 4. */ +#define ENDPOINT_TX_SIZE 0x01000200
+/* EP1 TX FIFO: 1024 bytes. start address: 0x220 * 4. */ +/* EP2 TX FIFO: 1024 bytes. start address: 0x320 * 4. */ +/* EP3 TX FIFO: 1024 bytes. start address: 0x420 * 4. */ +/* EP4 TX FIFO: 1024 bytes. start address: 0x520 * 4. */ +/* EP5 TX FIFO: 128 bytes. start address: 0x620 * 4. */ +/* EP6 TX FIFO: 128 bytes. start address: 0x640 * 4. */ +/* EP7 TX FIFO: 128 bytes. start address: 0x660 * 4. */ +/* EP8 TX FIFO: 128 bytes. start address: 0x680 * 4. */ +/* EP9 TX FIFO: 128 bytes. start address: 0x6A0 * 4. */ +/* EP10 TX FIFO: 128 bytes. start address: 0x6C0 * 4. */ +/* EP11 TX FIFO: 128 bytes. start address: 0x6E0 * 4. */ +/* EP12 TX FIFO: 128 bytes. start address: 0x700 * 4. */ +/* EP13 TX FIFO: 128 bytes. start address: 0x720 * 4. */ +/* EP14 TX FIFO: 128 bytes. start address: 0x740 * 4. */ +/* EP15 TX FIFO: 128 bytes. start address: 0x760 * 4. */
+#define DATA_IN_ENDPOINT_TX_FIFO1 0x01000220 +#define DATA_IN_ENDPOINT_TX_FIFO2 0x01000320 +#define DATA_IN_ENDPOINT_TX_FIFO3 0x01000420 +#define DATA_IN_ENDPOINT_TX_FIFO4 0x01000520 +#define DATA_IN_ENDPOINT_TX_FIFO5 0x00200620 +#define DATA_IN_ENDPOINT_TX_FIFO6 0x00200640 +#define DATA_IN_ENDPOINT_TX_FIFO7 0x00200680 +#define DATA_IN_ENDPOINT_TX_FIFO8 0x002006A0 +#define DATA_IN_ENDPOINT_TX_FIFO9 0x002006C0 +#define DATA_IN_ENDPOINT_TX_FIFO10 0x002006E0 +#define DATA_IN_ENDPOINT_TX_FIFO11 0x00200700 +#define DATA_IN_ENDPOINT_TX_FIFO12 0x00200720 +#define DATA_IN_ENDPOINT_TX_FIFO13 0x00200740 +#define DATA_IN_ENDPOINT_TX_FIFO14 0x00200760 +#define DATA_IN_ENDPOINT_TX_FIFO15 0x00200F00
+/*DWC_OTG regsiter descriptor*/ +/*Device mode CSR MAP*/ +#define DEVICE_CSR_BASE 0x800 +/*Device mode CSR MAP*/ +#define DEVICE_INEP_BASE 0x900 +/*Device mode CSR MAP*/ +#define DEVICE_OUTEP_BASE 0xB00
+/*** OTG LINK CORE REGISTERS ***/ +/* Core Global Registers */ +#define GOTGCTL 0x000 +#define GOTGINT 0x004 +#define GAHBCFG 0x008 +#define GAHBCFG_P_TXF_EMP_LVL (1 << 8) +#define GAHBCFG_NP_TXF_EMP_LVL (1 << 7) +#define GAHBCFG_DMA_EN (1 << 5) +#define GAHBCFG_GLBL_INTR_EN (1 << 0) +#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \
GAHBCFG_NP_TXF_EMP_LVL | \
GAHBCFG_DMA_EN | \
GAHBCFG_GLBL_INTR_EN)
+#define GUSBCFG 0x00C +#define GRSTCTL 0x010 +#define GRSTCTL_AHBIDLE (1 << 31) +#define GRSTCTL_CSFTRST (1 << 0)
+#define GINTSTS 0x014 +#define GINTSTS_WKUPINT BIT31 +#define GINTSTS_SESSREGINT BIT30 +#define GINTSTS_DISCONNINT BIT29 +#define GINTSTS_CONIDSTSCHNG BIT28 +#define GINTSTS_LPMTRANRCVD BIT27 +#define GINTSTS_PTXFEMP BIT26 +#define GINTSTS_HCHINT BIT25 +#define GINTSTS_PRTINT BIT24 +#define GINTSTS_RESETDET BIT23 +#define GINTSTS_FET_SUSP BIT22 +#define GINTSTS_INCOMPL_IP BIT21 +#define GINTSTS_INCOMPL_SOIN BIT20 +#define GINTSTS_OEPINT BIT19 +#define GINTSTS_IEPINT BIT18 +#define GINTSTS_EPMIS BIT17 +#define GINTSTS_RESTOREDONE BIT16 +#define GINTSTS_EOPF BIT15 +#define GINTSTS_ISOUTDROP BIT14 +#define GINTSTS_ENUMDONE BIT13 +#define GINTSTS_USBRST BIT12 +#define GINTSTS_USBSUSP BIT11 +#define GINTSTS_ERLYSUSP BIT10 +#define GINTSTS_I2CINT BIT9 +#define GINTSTS_ULPI_CK_INT BIT8 +#define GINTSTS_GOUTNAKEFF BIT7 +#define GINTSTS_GINNAKEFF BIT6 +#define GINTSTS_NPTXFEMP BIT5 +#define GINTSTS_RXFLVL BIT4 +#define GINTSTS_SOF BIT3 +#define GINTSTS_OTGINT BIT2 +#define GINTSTS_MODEMIS BIT1 +#define GINTSTS_CURMODE_HOST BIT0
+#define GINTMSK 0x018 +#define GRXSTSR 0x01C +#define GRXSTSP 0x020 +#define GRXFSIZ 0x024 +#define GNPTXFSIZ 0x028 +#define GNPTXSTS 0x02C
+#define GHWCFG1 0x044 +#define GHWCFG2 0x048 +#define GHWCFG3 0x04c +#define GHWCFG4 0x050 +#define GLPMCFG 0x054
+#define GDFIFOCFG 0x05c
+#define HPTXFSIZ 0x100 +#define DIEPTXF(x) (0x100 + 4 * (x)) +#define DIEPTXF1 0x104 +#define DIEPTXF2 0x108 +#define DIEPTXF3 0x10C +#define DIEPTXF4 0x110 +#define DIEPTXF5 0x114 +#define DIEPTXF6 0x118 +#define DIEPTXF7 0x11C +#define DIEPTXF8 0x120 +#define DIEPTXF9 0x124 +#define DIEPTXF10 0x128 +#define DIEPTXF11 0x12C +#define DIEPTXF12 0x130 +#define DIEPTXF13 0x134 +#define DIEPTXF14 0x138 +#define DIEPTXF15 0x13C
+/*** HOST MODE REGISTERS ***/ +/* Host Global Registers */ +#define HCFG 0x400 +#define HFIR 0x404 +#define HFNUM 0x408 +#define HPTXSTS 0x410 +#define HAINT 0x414 +#define HAINTMSK 0x418
+/* Host Port Control and Status Registers */ +#define HPRT 0x440
+/* Host Channel-Specific Registers */ +#define HCCHAR(x) (0x500 + 0x20 * (x)) +#define HCSPLT(x) (0x504 + 0x20 * (x)) +#define HCINT(x) (0x508 + 0x20 * (x)) +#define HCINTMSK(x) (0x50C + 0x20 * (x)) +#define HCTSIZ(x) (0x510 + 0x20 * (x)) +#define HCDMA(x) (0x514 + 0x20 * (x)) +#define HCCHAR0 0x500 +#define HCSPLT0 0x504 +#define HCINT0 0x508 +#define HCINTMSK0 0x50C +#define HCTSIZ0 0x510 +#define HCDMA0 0x514 +#define HCCHAR1 0x520 +#define HCSPLT1 0x524 +#define HCINT1 0x528 +#define HCINTMSK1 0x52C +#define HCTSIZ1 0x530 +#define HCDMA1 0x534 +#define HCCHAR2 0x540 +#define HCSPLT2 0x544 +#define HCINT2 0x548 +#define HCINTMSK2 0x54C +#define HCTSIZ2 0x550 +#define HCDMA2 0x554 +#define HCCHAR3 0x560 +#define HCSPLT3 0x564 +#define HCINT3 0x568 +#define HCINTMSK3 0x56C +#define HCTSIZ3 0x570 +#define HCDMA3 0x574 +#define HCCHAR4 0x580 +#define HCSPLT4 0x584 +#define HCINT4 0x588 +#define HCINTMSK4 0x58C +#define HCTSIZ4 0x590 +#define HCDMA4 0x594 +#define HCCHAR5 0x5A0 +#define HCSPLT5 0x5A4 +#define HCINT5 0x5A8 +#define HCINTMSK5 0x5AC +#define HCTSIZ5 0x5B0 +#define HCDMA5 0x5B4 +#define HCCHAR6 0x5C0 +#define HCSPLT6 0x5C4 +#define HCINT6 0x5C8 +#define HCINTMSK6 0x5CC +#define HCTSIZ6 0x5D0 +#define HCDMA6 0x5D4 +#define HCCHAR7 0x5E0 +#define HCSPLT7 0x5E4 +#define HCINT7 0x5E8 +#define HCINTMSK7 0x5EC +#define HCTSIZ7 0x5F0 +#define HCDMA7 0x5F4 +#define HCCHAR8 0x600 +#define HCSPLT8 0x604 +#define HCINT8 0x608 +#define HCINTMSK8 0x60C +#define HCTSIZ8 0x610 +#define HCDMA8 0x614 +#define HCCHAR9 0x620 +#define HCSPLT9 0x624 +#define HCINT9 0x628 +#define HCINTMSK9 0x62C +#define HCTSIZ9 0x630 +#define HCDMA9 0x634 +#define HCCHAR10 0x640 +#define HCSPLT10 0x644 +#define HCINT10 0x648 +#define HCINTMSK10 0x64C +#define HCTSIZ10 0x650 +#define HCDMA10 0x654 +#define HCCHAR11 0x660 +#define HCSPLT11 0x664 +#define HCINT11 0x668 +#define HCINTMSK11 0x66C +#define HCTSIZ11 0x670 +#define HCDMA11 0x674 +#define HCCHAR12 0x680 +#define HCSPLT12 0x684 +#define HCINT12 0x688 +#define HCINTMSK12 0x68C +#define HCTSIZ12 0x690 +#define HCDMA12 0x694 +#define HCCHAR13 0x6A0 +#define HCSPLT13 0x6A4 +#define HCINT13 0x6A8 +#define HCINTMSK13 0x6AC +#define HCTSIZ13 0x6B0 +#define HCDMA13 0x6B4 +#define HCCHAR14 0x6C0 +#define HCSPLT14 0x6C4 +#define HCINT14 0x6C8 +#define HCINTMSK14 0x6CC +#define HCTSIZ14 0x6D0 +#define HCDMA14 0x6D4 +#define HCCHAR15 0x6E0 +#define HCSPLT15 0x6E4 +#define HCINT15 0x6E8 +#define HCINTMSK15 0x6EC +#define HCTSIZ15 0x6F0 +#define HCDMA15 0x6F4
+/*** DEVICE MODE REGISTERS ***/ +/* Device Global Registers */ +#define DCFG 0x800 +#define DCFG_DESCDMA BIT23 +#define DCFG_EPMISCNT_MASK (0x1F << 18) +#define DCFG_EPMISCNT_SHIFT 18 +#define DCFG_DEVADDR_MASK (0x7F << 4) +#define DCFG_DEVADDR_SHIFT 4 +#define DCFG_DEVADDR(x) (((x) << DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK) +#define DCFG_NZ_STS_OUT_HSHK BIT2
+#define DCTL 0x804 +#define DCTL_PWRONPRGDONE BIT11 +#define DCTL_GNPINNAKSTS BIT2 +#define DCTL_SFTDISCON BIT1
+#define DSTS 0x808 +#define DIEPMSK 0x810 +#define DOEPMSK 0x814
+#define DXEPMSK_TIMEOUTMSK BIT3 +#define DXEPMSK_AHBERMSK BIT2 +#define DXEPMSK_XFERCOMPLMSK BIT0
+#define DAINT 0x818 +#define DAINTMSK 0x81C
+#define DAINTMSK_OUTEPMSK_SHIFT 16 +#define DAINTMSK_INEPMSK_SHIFT 0
+#define DTKNQR1 0x820 +#define DTKNQR2 0x824 +#define DVBUSDIS 0x828 +#define DVBUSPULSE 0x82C +#define DTHRCTL 0x830
+/* Device Logical IN Endpoint-Specific Registers */ +#define DIEPCTL(x) (0x900 + 0x20 * (x)) +#define DIEPINT(x) (0x908 + 0x20 * (x)) +#define DIEPTSIZ(x) (0x910 + 0x20 * (x)) +#define DIEPDMA(x) (0x914 + 0x20 * (x)) +#define DTXFSTS(x) (0x918 + 0x20 * (x))
+#define DIEPCTL0 0x900 +#define DIEPINT0 0x908 +#define DIEPTSIZ0 0x910 +#define DIEPDMA0 0x914 +#define DIEPCTL1 0x920 +#define DIEPINT1 0x928 +#define DIEPTSIZ1 0x930 +#define DIEPDMA1 0x934 +#define DIEPCTL2 0x940 +#define DIEPINT2 0x948 +#define DIEPTSIZ2 0x950 +#define DIEPDMA2 0x954 +#define DIEPCTL3 0x960 +#define DIEPINT3 0x968 +#define DIEPTSIZ3 0x970 +#define DIEPDMA3 0x974 +#define DIEPCTL4 0x980 +#define DIEPINT4 0x988 +#define DIEPTSIZ4 0x990 +#define DIEPDMA4 0x994 +#define DIEPCTL5 0x9A0 +#define DIEPINT5 0x9A8 +#define DIEPTSIZ5 0x9B0 +#define DIEPDMA5 0x9B4 +#define DIEPCTL6 0x9C0 +#define DIEPINT6 0x9C8 +#define DIEPTSIZ6 0x9D0 +#define DIEPDMA6 0x9D4 +#define DIEPCTL7 0x9E0 +#define DIEPINT7 0x9E8 +#define DIEPTSIZ7 0x9F0 +#define DIEPDMA7 0x9F4 +#define DIEPCTL8 0xA00 +#define DIEPINT8 0xA08 +#define DIEPTSIZ8 0xA10 +#define DIEPDMA8 0xA14 +#define DIEPCTL9 0xA20 +#define DIEPINT9 0xA28 +#define DIEPTSIZ9 0xA30 +#define DIEPDMA9 0xA34 +#define DIEPCTL10 0xA40 +#define DIEPINT10 0xA48 +#define DIEPTSIZ10 0xA50 +#define DIEPDMA10 0xA54 +#define DIEPCTL11 0xA60 +#define DIEPINT11 0xA68 +#define DIEPTSIZ11 0xA70 +#define DIEPDMA11 0xA74 +#define DIEPCTL12 0xA80 +#define DIEPINT12 0xA88 +#define DIEPTSIZ12 0xA90 +#define DIEPDMA12 0xA94 +#define DIEPCTL13 0xAA0 +#define DIEPINT13 0xAA8 +#define DIEPTSIZ13 0xAB0 +#define DIEPDMA13 0xAB4 +#define DIEPCTL14 0xAC0 +#define DIEPINT14 0xAC8 +#define DIEPTSIZ14 0xAD0 +#define DIEPDMA14 0xAD4 +#define DIEPCTL15 0xAE0 +#define DIEPINT15 0xAE8 +#define DIEPTSIZ15 0xAF0 +#define DIEPDMA15 0xAF4
+/* Device Logical OUT Endpoint-Specific Registers */ +#define DOEPCTL(x) (0xB00 + 0x20 * (x)) +#define DOEPINT(x) (0xB08 + 0x20 * (x)) +#define DOEPTSIZ(x) (0xB10 + 0x20 * (x))
+#define DXEPINT_EPDISBLD BIT1 +#define DXEPINT_XFERCOMPL BIT0
+#define DXEPTSIZ_SUPCNT(x) (((x) & 0x3) << 29) +#define DXEPTSIZ_PKTCNT(x) (((x) & 0x3) << 19) +#define DXEPTSIZ_XFERSIZE(x) ((x) & 0x7F)
+#define DOEPDMA(x) (0xB14 + 0x20 * (x)) +#define DOEPCTL0 0xB00 +#define DOEPINT0 0xB08 +#define DOEPTSIZ0 0xB10 +#define DOEPDMA0 0xB14 +#define DOEPCTL1 0xB20 +#define DOEPINT1 0xB28 +#define DOEPTSIZ1 0xB30 +#define DOEPDMA1 0xB34 +#define DOEPCTL2 0xB40 +#define DOEPINT2 0xB48 +#define DOEPTSIZ2 0xB50 +#define DOEPDMA2 0xB54 +#define DOEPCTL3 0xB60 +#define DOEPINT3 0xB68 +#define DOEPTSIZ3 0xB70 +#define DOEPDMA3 0xB74 +#define DOEPCTL4 0xB80 +#define DOEPINT4 0xB88 +#define DOEPTSIZ4 0xB90 +#define DOEPDMA4 0xB94 +#define DOEPCTL5 0xBA0 +#define DOEPINT5 0xBA8 +#define DOEPTSIZ5 0xBB0 +#define DOEPDMA5 0xBB4 +#define DOEPCTL6 0xBC0 +#define DOEPINT6 0xBC8 +#define DOEPTSIZ6 0xBD0 +#define DOEPDMA6 0xBD4 +#define DOEPCTL7 0xBE0 +#define DOEPINT7 0xBE8 +#define DOEPTSIZ7 0xBF0 +#define DOEPDMA7 0xBF4 +#define DOEPCTL8 0xC00 +#define DOEPINT8 0xC08 +#define DOEPTSIZ8 0xC10 +#define DOEPDMA8 0xC14 +#define DOEPCTL9 0xC20 +#define DOEPINT9 0xC28 +#define DOEPTSIZ9 0xC30 +#define DOEPDMA9 0xC34 +#define DOEPCTL10 0xC40 +#define DOEPINT10 0xC48 +#define DOEPTSIZ10 0xC50 +#define DOEPDMA10 0xC54 +#define DOEPCTL11 0xC60 +#define DOEPINT11 0xC68 +#define DOEPTSIZ11 0xC70 +#define DOEPDMA11 0xC74 +#define DOEPCTL12 0xC80 +#define DOEPINT12 0xC88 +#define DOEPTSIZ12 0xC90 +#define DOEPDMA12 0xC94 +#define DOEPCTL13 0xCA0 +#define DOEPINT13 0xCA8 +#define DOEPTSIZ13 0xCB0 +#define DOEPDMA13 0xCB4 +#define DOEPCTL14 0xCC0 +#define DOEPINT14 0xCC8 +#define DOEPTSIZ14 0xCD0 +#define DOEPDMA14 0xCD4 +#define DOEPCTL15 0xCE0 +#define DOEPINT15 0xCE8 +#define DOEPTSIZ15 0xCF0 +#define DOEPDMA15 0xCF4
+#define DXEPCTL_EPENA BIT31 +#define DXEPCTL_SNAK BIT27 +#define DXEPCTL_CNAK BIT26 +#define DXEPCTL_STALL BIT21 +#define DXEPCTL_EPTYPE_MASK (BIT19 | BIT18) +#define DXEPCTL_NAKSTS BIT17 +#define DXEPCTL_USBACTEP BIT15 +#define DXEPCTL_MPS_MASK 0x7FF
+/* Power and Clock Gating Register */ +#define PCGCCTL 0xE00
+#define EP0FIFO 0x1000
+/**
- This union represents the bit fields in the DMA Descriptor
- status quadlet. Read the quadlet into the <i>d32</i> member then
- set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
- <i>b_iso_in</i> elements.
- */
+typedef union {
- /** raw register data */
- UINT32 d32;
- /** quadlet bits */
- struct {
- /** Received number of bytes */
- unsigned bytes:16;
- /** NAK bit - only for OUT EPs */
- unsigned nak:1;
- unsigned reserved17_22:6;
- /** Multiple Transfer - only for OUT EPs */
- unsigned mtrf:1;
- /** Setup Packet received - only for OUT EPs */
- unsigned sr:1;
- /** Interrupt On Complete */
- unsigned ioc:1;
- /** Short Packet */
- unsigned sp:1;
- /** Last */
- unsigned l:1;
- /** Receive Status */
- unsigned sts:2;
- /** Buffer Status */
- unsigned bs:2;
- } b;
+} dev_dma_desc_sts_t;
+/**
- DMA Descriptor structure
- DMA Descriptor structure contains two quadlets:
- Status quadlet and Data buffer pointer.
- */
+typedef struct {
- /** DMA Descriptor status quadlet */
- dev_dma_desc_sts_t status;
- /** DMA Descriptor data buffer pointer */
- UINT32 buf;
+} dwc_otg_dev_dma_desc_t;
+#endif //ifndef __DW_USB_DXE_H__ diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf new file mode 100644 index 0000000..fc1e988 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf @@ -0,0 +1,52 @@ +#/** @file +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/
+[Defines]
- INF_VERSION = 0x00010019
- BASE_NAME = DwUsbDxe
- FILE_GUID = 72d78ea6-4dee-11e3-8100-f3842a48d0a0
Please use a fresh GUID rather than the one from
EmbeddedPkg/Drivers/Isp1761UsbDxe/Isp1761UsbDxe.inf: FILE_GUID = 72d78ea6-4dee-11e3-8100-f3842a48d0a0
- MODULE_TYPE = UEFI_DRIVER
- VERSION_STRING = 1.0
- ENTRY_POINT = DwUsbEntryPoint
+[Sources.common]
- DwUsbDxe.c
+[LibraryClasses]
- ArmLib
- DebugLib
- IoLib
- MemoryAllocationLib
- TimerLib
- UefiBootServicesTableLib
- UefiDriverEntryPoint
- UncachedMemoryAllocationLib
- CacheMaintenanceLib
+[Protocols]
- gEfiDriverBindingProtocolGuid
- gUsbDeviceProtocolGuid
+[Packages]
- ArmPkg/ArmPkg.dec
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- EmbeddedPkg/EmbeddedPkg.dec
- OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
+[Pcd]
- gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress
+[Depex]
- BEFORE gAndroidFastbootUsbGuid
This is the wrong way around.
If the Android fastboot driver depends on a protocol produced by this driver, it should depex on that.
Using depexes like this completely breaks the modular nature of UEFI, and makes it very difficult to create variations of a platform by selectively changing drivers.
diff --git a/Include/Protocol/DwUsb.h b/Include/Protocol/DwUsb.h new file mode 100644 index 0000000..040e126 --- /dev/null +++ b/Include/Protocol/DwUsb.h @@ -0,0 +1,81 @@ +/** @file
- Copyright (c) 2015-2017, Linaro. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef __DW_USB_H__ +#define __DW_USB_H__
+// +// Protocol GUID +// +#define DW_USB_PROTOCOL_GUID { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }}
+// +// Protocol interface structure +// +typedef struct _DW_USB_PROTOCOL DW_USB_PROTOCOL;
+#define USB_HOST_MODE 0 +#define USB_DEVICE_MODE 1 +#define USB_CABLE_NOT_ATTACHED 2
+#define LANG_LENGTH 8 +#define MANU_FACTURER_STRING_LENGTH 32 +#define PRODUCT_STRING_LENGTH 32 +#define SERIAL_STRING_LENGTH 17
+typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_LANG) (
- OUT CHAR16 *Lang,
- OUT UINT8 *Length
- );
+typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_MANU_FACTURER) (
- OUT CHAR16 *ManuFacturer,
- OUT UINT8 *Length
- );
+typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_PRODUCT) (
- OUT CHAR16 *Product,
- OUT UINT8 *Length
- );
+typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_SERIAL_NO) (
- OUT CHAR16 *SerialNo,
- OUT UINT8 *Length
- );
+typedef +EFI_STATUS +(EFIAPI *DW_USB_PHY_INIT) (
- IN UINT8 Mode
- );
+struct _DW_USB_PROTOCOL {
- DW_USB_GET_LANG GetLang;
- DW_USB_GET_MANU_FACTURER GetManuFacturer;
- DW_USB_GET_PRODUCT GetProduct;
- DW_USB_GET_SERIAL_NO GetSerialNo;
- DW_USB_PHY_INIT PhyInit;
+};
+extern EFI_GUID gDwUsbProtocolGuid;
+#endif
2.7.4
These GUIDs are used in HiKeyUsb and HiKeyGpio driver.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org --- Platforms/Hisilicon/HiKey/HiKey.dec | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/Platforms/Hisilicon/HiKey/HiKey.dec b/Platforms/Hisilicon/HiKey/HiKey.dec index 537138e..c4a4ad3 100644 --- a/Platforms/Hisilicon/HiKey/HiKey.dec +++ b/Platforms/Hisilicon/HiKey/HiKey.dec @@ -29,7 +29,10 @@ Include # Root include for the package
[Guids.common] + gArmPL061GpioGuid = { 0x5c1997d7, 0x8d45, 0x4f21, { 0xaf, 0x3c, 0x22, 0x06, 0xb8, 0xed, 0x8b, 0xec } } + gDwUsbDeviceGuid = { 0x72d78ea6, 0x4dee, 0x11e3, { 0x81, 0x00, 0xf3, 0x84, 0x2a, 0x48, 0xd0, 0xa0 } } gHiKeyTokenSpaceGuid = { 0x91148425, 0xcdd2, 0x4830, { 0x8b, 0xd0, 0xc6, 0x1c, 0x6d, 0xea, 0x36, 0x21 } } + gHiKeyVariableGuid = { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } }
[PcdsFixedAtBuild.common] gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L""|VOID*|0x00000001
Support PL061 GPIO controller on HiKey platform.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org --- .../Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c | 68 ++++++++++++++++++++++ .../Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf | 37 ++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf
diff --git a/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c new file mode 100644 index 0000000..9e7a895 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c @@ -0,0 +1,68 @@ +/** @file +* +* Copyright (c) 2015-2017, Linaro. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/EmbeddedGpio.h> + +GPIO_CONTROLLER gGpioDevice[]= { + { 0xf8011000, 0, 8 }, // GPIO0 + { 0xf8012000, 8, 8 }, // GPIO1 + { 0xf8013000, 16, 8 }, // GPIO2 + { 0xf8014000, 24, 8 }, // GPIO3 + { 0xf7020000, 32, 8 }, // GPIO4 + { 0xf7021000, 40, 8 }, // GPIO5 + { 0xf7022000, 48, 8 }, // GPIO6 + { 0xf7023000, 56, 8 }, // GPIO7 + { 0xf7024000, 64, 8 }, // GPIO8 + { 0xf7025000, 72, 8 }, // GPIO9 + { 0xf7026000, 80, 8 }, // GPIO10 + { 0xf7027000, 88, 8 }, // GPIO11 + { 0xf7028000, 96, 8 }, // GPIO12 + { 0xf7029000, 104, 8 }, // GPIO13 + { 0xf702a000, 112, 8 }, // GPIO14 + { 0xf702b000, 120, 8 }, // GPIO15 + { 0xf702c000, 128, 8 }, // GPIO16 + { 0xf702d000, 136, 8 }, // GPIO17 + { 0xf702e000, 144, 8 }, // GPIO18 + { 0xf702f000, 152, 8 } // GPIO19 +}; + +PLATFORM_GPIO_CONTROLLER gPlatformGpioDevice = { + 160, 20, gGpioDevice +}; + +EFI_STATUS +EFIAPI +HiKeyGpioEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + // Install the Embedded Platform GPIO Protocol onto a new handle + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces( + &Handle, + &gPlatformGpioProtocolGuid, &gPlatformGpioDevice, + NULL + ); + if (EFI_ERROR(Status)) { + Status = EFI_OUT_OF_RESOURCES; + } + + return Status; +} diff --git a/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf new file mode 100644 index 0000000..4d43a92 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf @@ -0,0 +1,37 @@ +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = HiKeyGpio + FILE_GUID = b51a851c-7bf7-463f-b261-cfb158b7f699 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HiKeyGpioEntryPoint + +[Sources.common] + HiKeyGpioDxe.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec + +[LibraryClasses] + DebugLib + UefiDriverEntryPoint + +[Protocols] + gPlatformGpioProtocolGuid + +[Depex] + BEFORE gArmPL061GpioGuid
On 4 February 2017 at 05:13, Haojian Zhuang haojian.zhuang@linaro.org wrote:
Support PL061 GPIO controller on HiKey platform.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org
.../Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c | 68 ++++++++++++++++++++++ .../Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf | 37 ++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf
diff --git a/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c new file mode 100644 index 0000000..9e7a895 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c @@ -0,0 +1,68 @@ +/** @file +* +* Copyright (c) 2015-2017, Linaro. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/EmbeddedGpio.h>
+GPIO_CONTROLLER gGpioDevice[]= {
- { 0xf8011000, 0, 8 }, // GPIO0
- { 0xf8012000, 8, 8 }, // GPIO1
- { 0xf8013000, 16, 8 }, // GPIO2
- { 0xf8014000, 24, 8 }, // GPIO3
- { 0xf7020000, 32, 8 }, // GPIO4
- { 0xf7021000, 40, 8 }, // GPIO5
- { 0xf7022000, 48, 8 }, // GPIO6
- { 0xf7023000, 56, 8 }, // GPIO7
- { 0xf7024000, 64, 8 }, // GPIO8
- { 0xf7025000, 72, 8 }, // GPIO9
- { 0xf7026000, 80, 8 }, // GPIO10
- { 0xf7027000, 88, 8 }, // GPIO11
- { 0xf7028000, 96, 8 }, // GPIO12
- { 0xf7029000, 104, 8 }, // GPIO13
- { 0xf702a000, 112, 8 }, // GPIO14
- { 0xf702b000, 120, 8 }, // GPIO15
- { 0xf702c000, 128, 8 }, // GPIO16
- { 0xf702d000, 136, 8 }, // GPIO17
- { 0xf702e000, 144, 8 }, // GPIO18
- { 0xf702f000, 152, 8 } // GPIO19
+};
+PLATFORM_GPIO_CONTROLLER gPlatformGpioDevice = {
- 160, 20, gGpioDevice
+};
+EFI_STATUS +EFIAPI +HiKeyGpioEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
+{
- EFI_STATUS Status;
- EFI_HANDLE Handle;
- // Install the Embedded Platform GPIO Protocol onto a new handle
- Handle = NULL;
- Status = gBS->InstallMultipleProtocolInterfaces(
&Handle,
&gPlatformGpioProtocolGuid, &gPlatformGpioDevice,
NULL
);
- if (EFI_ERROR(Status)) {
- Status = EFI_OUT_OF_RESOURCES;
- }
- return Status;
+} diff --git a/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf new file mode 100644 index 0000000..4d43a92 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf @@ -0,0 +1,37 @@ +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +#
+[Defines]
- INF_VERSION = 0x00010019
- BASE_NAME = HiKeyGpio
- FILE_GUID = b51a851c-7bf7-463f-b261-cfb158b7f699
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
- ENTRY_POINT = HiKeyGpioEntryPoint
+[Sources.common]
- HiKeyGpioDxe.c
+[Packages]
- EmbeddedPkg/EmbeddedPkg.dec
- MdePkg/MdePkg.dec
- OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec
+[LibraryClasses]
- DebugLib
- UefiDriverEntryPoint
+[Protocols]
- gPlatformGpioProtocolGuid
+[Depex]
- BEFORE gArmPL061GpioGuid
This is the wrong way around: it appears that PL061GpioDxe depends on gPlatformGpioProtocolGuid, which is produced by this driver. This driver does not invoke any other protocols, so its depex should be TRUE. Instead, we should fix the depex of the PL061GpioDxe driver.
Support Designware USB device controller on HiKey platform.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org --- .../Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c | 266 +++++++++++++++++++++ .../Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf | 46 ++++ 2 files changed, 312 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf
diff --git a/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c new file mode 100644 index 0000000..60ad4d6 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c @@ -0,0 +1,266 @@ +/** @file +* +* Copyright (c) 2015-2017, Linaro. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/TimerLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> + +#include <Protocol/EmbeddedGpio.h> +#include <Protocol/DwUsb.h> + +#include <Hi6220.h> + + +#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 + +// Jumper on pin5-6 of J15 determines whether boot to fastboot +#define DETECT_J15_FASTBOOT 24 // GPIO 3_0 + +STATIC EMBEDDED_GPIO *mGpio; + +STATIC +VOID +HiKeyDetectUsbModeInit ( + IN VOID + ) +{ + EFI_STATUS Status; + + /* set pullup on both GPIO2_5 & GPIO2_6. It's required for inupt. */ + MmioWrite32 (0xf8001864, 1); + MmioWrite32 (0xf8001868, 1); + + Status = gBS->LocateProtocol (&gEmbeddedGpioProtocolGuid, NULL, (VOID **)&mGpio); + ASSERT_EFI_ERROR (Status); + Status = mGpio->Set (mGpio, USB_SEL_GPIO0_3, GPIO_MODE_OUTPUT_0); + ASSERT_EFI_ERROR (Status); + Status = mGpio->Set (mGpio, USB_5V_HUB_EN, GPIO_MODE_OUTPUT_0); + ASSERT_EFI_ERROR (Status); + MicroSecondDelay (1000); + + Status = mGpio->Set (mGpio, USB_ID_DET_GPIO2_5, GPIO_MODE_INPUT); + ASSERT_EFI_ERROR (Status); + Status = mGpio->Set (mGpio, USB_VBUS_DET_GPIO2_6, GPIO_MODE_INPUT); + ASSERT_EFI_ERROR (Status); +} + +UINTN +HiKeyGetUsbMode ( + IN VOID + ) +{ +#if 0 + EFI_STATUS Status; + UINTN GpioId, GpioVbus; + UINTN Value; + + Status = mGpio->Get (mGpio, USB_ID_DET_GPIO2_5, &Value); + ASSERT_EFI_ERROR (Status); + GpioId = Value; + Status = mGpio->Get (mGpio, USB_VBUS_DET_GPIO2_6, &Value); + ASSERT_EFI_ERROR (Status); + GpioVbus = Value; + +DEBUG ((DEBUG_ERROR, "#%a, %d, GpioId:%d, GpioVbus:%d\n", __func__, __LINE__, GpioId, GpioVbus)); + if ((GpioId == 1) && (GpioVbus == 0)) { + return USB_DEVICE_MODE; + } else if ((GpioId == 0) && (GpioVbus == 1)) { + return USB_CABLE_NOT_ATTACHED; + } + return USB_HOST_MODE; +#else + return USB_DEVICE_MODE; +#endif +} + +EFI_STATUS +HiKeyUsbPhyInit ( + IN UINT8 Mode + ) +{ + UINTN Value; + UINT32 Data; + + HiKeyDetectUsbModeInit (); + + //setup clock + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN0, BIT4); + do { + Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CLKSTAT0); + } while ((Value & BIT4) == 0); + + //setup phy + Data = RST0_USBOTG_BUS | RST0_POR_PICOPHY | + RST0_USBOTG | RST0_USBOTG_32K; + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS0, Data); + do { + Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_RSTSTAT0); + Value &= Data; + } while (Value); + + Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4); + Value &= ~(CTRL4_PICO_SIDDQ | CTRL4_FPGA_EXT_PHY_SEL | + CTRL4_OTG_PHY_SEL); + Value |= CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL; + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4, Value); + MicroSecondDelay (1000); + + //If Mode = 1, USB in Device Mode + //If Mode = 0, USB in Host Mode + if (Mode == USB_DEVICE_MODE) { + if (HiKeyGetUsbMode () == USB_DEVICE_MODE) { + DEBUG ((DEBUG_ERROR, "usb work as device mode.\n")); + } else { + return EFI_INVALID_PARAMETER; + } + + Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5); + Value &= ~CTRL5_PICOPHY_BC_MODE; + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Value); + MicroSecondDelay (20000); + } else { + if (HiKeyGetUsbMode () == USB_HOST_MODE) { + DEBUG ((DEBUG_ERROR, "usb work as host mode.\n")); + } else { + return EFI_INVALID_PARAMETER; + } + + /*CTRL5*/ + Data = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5); + Data &= ~CTRL5_PICOPHY_BC_MODE; + Data |= CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB | + CTRL5_PICOPHY_VDATDETENB | CTRL5_PICOPHY_DCDENB; + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Data); + MicroSecondDelay (20000); + MmioWrite32 (PERI_CTRL_BASE + 0x018, 0x70533483); //EYE_PATTERN + + MicroSecondDelay (5000); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiKeyUsbGetLang ( + OUT CHAR16 *Lang, + OUT UINT8 *Length + ) +{ + if ((Lang == NULL) || (Length == NULL)) { + return EFI_INVALID_PARAMETER; + } + Lang[0] = 0x409; + *Length = sizeof (CHAR16); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiKeyUsbGetManuFacturer ( + OUT CHAR16 *ManuFacturer, + OUT UINT8 *Length + ) +{ + UINTN VariableSize; + CHAR16 DataUnicode[MANU_FACTURER_STRING_LENGTH]; + + if ((ManuFacturer == NULL) || (Length == NULL)) { + return EFI_INVALID_PARAMETER; + } + VariableSize = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16); + ZeroMem (DataUnicode, MANU_FACTURER_STRING_LENGTH * sizeof(CHAR16)); + StrCpy (DataUnicode, L"96Boards"); + CopyMem (ManuFacturer, DataUnicode, VariableSize); + *Length = VariableSize; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiKeyUsbGetProduct ( + OUT CHAR16 *Product, + OUT UINT8 *Length + ) +{ + UINTN VariableSize; + CHAR16 DataUnicode[PRODUCT_STRING_LENGTH]; + + if ((Product == NULL) || (Length == NULL)) { + return EFI_INVALID_PARAMETER; + } + VariableSize = PRODUCT_STRING_LENGTH * sizeof (CHAR16); + ZeroMem (DataUnicode, PRODUCT_STRING_LENGTH * sizeof(CHAR16)); + StrCpy (DataUnicode, L"HiKey"); + CopyMem (Product, DataUnicode, VariableSize); + *Length = VariableSize; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiKeyUsbGetSerialNo ( + OUT CHAR16 *SerialNo, + OUT UINT8 *Length + ) +{ + UINTN VariableSize; + CHAR16 DataUnicode[SERIAL_STRING_LENGTH]; + + if ((SerialNo == NULL) || (Length == NULL)) { + return EFI_INVALID_PARAMETER; + } + VariableSize = SERIAL_STRING_LENGTH * sizeof (CHAR16); + ZeroMem (DataUnicode, SERIAL_STRING_LENGTH * sizeof(CHAR16)); + StrCpy (DataUnicode, L"0123456789abcdef"); + CopyMem (SerialNo, DataUnicode, VariableSize); + *Length = VariableSize; + return EFI_SUCCESS; +} + +DW_USB_PROTOCOL mDwUsbDevice = { + HiKeyUsbGetLang, + HiKeyUsbGetManuFacturer, + HiKeyUsbGetProduct, + HiKeyUsbGetSerialNo, + HiKeyUsbPhyInit +}; + +EFI_STATUS +EFIAPI +HiKeyUsbEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gDwUsbProtocolGuid, + EFI_NATIVE_INTERFACE, + &mDwUsbDevice + ); + if (EFI_ERROR (Status)) { + return Status; + } + return Status; +} diff --git a/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf new file mode 100644 index 0000000..75ff599 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf @@ -0,0 +1,46 @@ +#/** @file +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = HiKeyUsbDxe + FILE_GUID = c5c7089e-9b00-448c-8b23-a552688e2833 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HiKeyUsbEntryPoint + +[Sources.common] + HiKeyUsbDxe.c + +[LibraryClasses] + DebugLib + IoLib + TimerLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gDwUsbProtocolGuid + gEfiDriverBindingProtocolGuid + gEmbeddedGpioProtocolGuid + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec + +[Depex] + BEFORE gDwUsbDeviceGuid
On 02/03/2017 11:13 PM, Haojian Zhuang wrote:
Support Designware USB device controller on HiKey platform.
Hi,
Are there plans to support this controller as a USB host rather than just a fastboot device?
Thanks,
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org
.../Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c | 266 +++++++++++++++++++++ .../Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf | 46 ++++ 2 files changed, 312 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf
diff --git a/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c new file mode 100644 index 0000000..60ad4d6 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c @@ -0,0 +1,266 @@ +/** @file +* +* Copyright (c) 2015-2017, Linaro. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/
+#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/TimerLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/EmbeddedGpio.h> +#include <Protocol/DwUsb.h>
+#include <Hi6220.h>
+#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
+// Jumper on pin5-6 of J15 determines whether boot to fastboot +#define DETECT_J15_FASTBOOT 24 // GPIO 3_0
+STATIC EMBEDDED_GPIO *mGpio;
+STATIC +VOID +HiKeyDetectUsbModeInit (
- IN VOID
- )
+{
- EFI_STATUS Status;
- /* set pullup on both GPIO2_5 & GPIO2_6. It's required for inupt. */
- MmioWrite32 (0xf8001864, 1);
- MmioWrite32 (0xf8001868, 1);
- Status = gBS->LocateProtocol (&gEmbeddedGpioProtocolGuid, NULL, (VOID **)&mGpio);
- ASSERT_EFI_ERROR (Status);
- Status = mGpio->Set (mGpio, USB_SEL_GPIO0_3, GPIO_MODE_OUTPUT_0);
- ASSERT_EFI_ERROR (Status);
- Status = mGpio->Set (mGpio, USB_5V_HUB_EN, GPIO_MODE_OUTPUT_0);
- ASSERT_EFI_ERROR (Status);
- MicroSecondDelay (1000);
- Status = mGpio->Set (mGpio, USB_ID_DET_GPIO2_5, GPIO_MODE_INPUT);
- ASSERT_EFI_ERROR (Status);
- Status = mGpio->Set (mGpio, USB_VBUS_DET_GPIO2_6, GPIO_MODE_INPUT);
- ASSERT_EFI_ERROR (Status);
+}
+UINTN +HiKeyGetUsbMode (
- IN VOID
- )
+{ +#if 0
- EFI_STATUS Status;
- UINTN GpioId, GpioVbus;
- UINTN Value;
- Status = mGpio->Get (mGpio, USB_ID_DET_GPIO2_5, &Value);
- ASSERT_EFI_ERROR (Status);
- GpioId = Value;
- Status = mGpio->Get (mGpio, USB_VBUS_DET_GPIO2_6, &Value);
- ASSERT_EFI_ERROR (Status);
- GpioVbus = Value;
+DEBUG ((DEBUG_ERROR, "#%a, %d, GpioId:%d, GpioVbus:%d\n", __func__, __LINE__, GpioId, GpioVbus));
- if ((GpioId == 1) && (GpioVbus == 0)) {
- return USB_DEVICE_MODE;
- } else if ((GpioId == 0) && (GpioVbus == 1)) {
- return USB_CABLE_NOT_ATTACHED;
- }
- return USB_HOST_MODE;
+#else
- return USB_DEVICE_MODE;
+#endif +}
+EFI_STATUS +HiKeyUsbPhyInit (
- IN UINT8 Mode
- )
+{
- UINTN Value;
- UINT32 Data;
- HiKeyDetectUsbModeInit ();
- //setup clock
- MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN0, BIT4);
- do {
Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CLKSTAT0);
- } while ((Value & BIT4) == 0);
- //setup phy
- Data = RST0_USBOTG_BUS | RST0_POR_PICOPHY |
RST0_USBOTG | RST0_USBOTG_32K;
- MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS0, Data);
- do {
- Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_RSTSTAT0);
- Value &= Data;
- } while (Value);
- Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4);
- Value &= ~(CTRL4_PICO_SIDDQ | CTRL4_FPGA_EXT_PHY_SEL |
CTRL4_OTG_PHY_SEL);
- Value |= CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL;
- MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4, Value);
- MicroSecondDelay (1000);
- //If Mode = 1, USB in Device Mode
- //If Mode = 0, USB in Host Mode
- if (Mode == USB_DEVICE_MODE) {
- if (HiKeyGetUsbMode () == USB_DEVICE_MODE) {
DEBUG ((DEBUG_ERROR, "usb work as device mode.\n"));
- } else {
return EFI_INVALID_PARAMETER;
- }
Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5);
Value &= ~CTRL5_PICOPHY_BC_MODE;
MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Value);
MicroSecondDelay (20000);
- } else {
- if (HiKeyGetUsbMode () == USB_HOST_MODE) {
DEBUG ((DEBUG_ERROR, "usb work as host mode.\n"));
- } else {
return EFI_INVALID_PARAMETER;
- }
- /*CTRL5*/
- Data = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5);
- Data &= ~CTRL5_PICOPHY_BC_MODE;
- Data |= CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB |
CTRL5_PICOPHY_VDATDETENB | CTRL5_PICOPHY_DCDENB;
- MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Data);
- MicroSecondDelay (20000);
- MmioWrite32 (PERI_CTRL_BASE + 0x018, 0x70533483); //EYE_PATTERN
- MicroSecondDelay (5000);
- }
- return EFI_SUCCESS;
+}
+EFI_STATUS +EFIAPI +HiKeyUsbGetLang (
- OUT CHAR16 *Lang,
- OUT UINT8 *Length
- )
+{
- if ((Lang == NULL) || (Length == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- Lang[0] = 0x409;
- *Length = sizeof (CHAR16);
- return EFI_SUCCESS;
+}
+EFI_STATUS +EFIAPI +HiKeyUsbGetManuFacturer (
- OUT CHAR16 *ManuFacturer,
- OUT UINT8 *Length
- )
+{
- UINTN VariableSize;
- CHAR16 DataUnicode[MANU_FACTURER_STRING_LENGTH];
- if ((ManuFacturer == NULL) || (Length == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- VariableSize = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);
- ZeroMem (DataUnicode, MANU_FACTURER_STRING_LENGTH * sizeof(CHAR16));
- StrCpy (DataUnicode, L"96Boards");
- CopyMem (ManuFacturer, DataUnicode, VariableSize);
- *Length = VariableSize;
- return EFI_SUCCESS;
+}
+EFI_STATUS +EFIAPI +HiKeyUsbGetProduct (
- OUT CHAR16 *Product,
- OUT UINT8 *Length
- )
+{
- UINTN VariableSize;
- CHAR16 DataUnicode[PRODUCT_STRING_LENGTH];
- if ((Product == NULL) || (Length == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- VariableSize = PRODUCT_STRING_LENGTH * sizeof (CHAR16);
- ZeroMem (DataUnicode, PRODUCT_STRING_LENGTH * sizeof(CHAR16));
- StrCpy (DataUnicode, L"HiKey");
- CopyMem (Product, DataUnicode, VariableSize);
- *Length = VariableSize;
- return EFI_SUCCESS;
+}
+EFI_STATUS +EFIAPI +HiKeyUsbGetSerialNo (
- OUT CHAR16 *SerialNo,
- OUT UINT8 *Length
- )
+{
- UINTN VariableSize;
- CHAR16 DataUnicode[SERIAL_STRING_LENGTH];
- if ((SerialNo == NULL) || (Length == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- VariableSize = SERIAL_STRING_LENGTH * sizeof (CHAR16);
- ZeroMem (DataUnicode, SERIAL_STRING_LENGTH * sizeof(CHAR16));
- StrCpy (DataUnicode, L"0123456789abcdef");
- CopyMem (SerialNo, DataUnicode, VariableSize);
- *Length = VariableSize;
- return EFI_SUCCESS;
+}
+DW_USB_PROTOCOL mDwUsbDevice = {
- HiKeyUsbGetLang,
- HiKeyUsbGetManuFacturer,
- HiKeyUsbGetProduct,
- HiKeyUsbGetSerialNo,
- HiKeyUsbPhyInit
+};
+EFI_STATUS +EFIAPI +HiKeyUsbEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
+{
- EFI_STATUS Status;
- Status = gBS->InstallProtocolInterface (
&ImageHandle,
&gDwUsbProtocolGuid,
EFI_NATIVE_INTERFACE,
&mDwUsbDevice
);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- return Status;
+} diff --git a/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf new file mode 100644 index 0000000..75ff599 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf @@ -0,0 +1,46 @@ +#/** @file +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/
+[Defines]
- INF_VERSION = 0x00010019
- BASE_NAME = HiKeyUsbDxe
- FILE_GUID = c5c7089e-9b00-448c-8b23-a552688e2833
- MODULE_TYPE = UEFI_DRIVER
- VERSION_STRING = 1.0
- ENTRY_POINT = HiKeyUsbEntryPoint
+[Sources.common]
- HiKeyUsbDxe.c
+[LibraryClasses]
- DebugLib
- IoLib
- TimerLib
- UefiBootServicesTableLib
- UefiDriverEntryPoint
+[Protocols]
- gDwUsbProtocolGuid
- gEfiDriverBindingProtocolGuid
- gEmbeddedGpioProtocolGuid
+[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- EmbeddedPkg/EmbeddedPkg.dec
- OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec
- OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec
+[Depex]
- BEFORE gDwUsbDeviceGuid
On 6 February 2017 at 17:43, Jeremy Linton jeremy.linton@arm.com wrote:
On 02/03/2017 11:13 PM, Haojian Zhuang wrote:
Support Designware USB device controller on HiKey platform.
Hi,
Are there plans to support this controller as a USB host rather than just a fastboot device?
There is a separate host mode driver for it, which they disabled on HiKey (I think) because it broke something else, presumably fastboot.
It is the same IP as Raspberry Pi 3, and I spent some time porting that a couple of months ago (without any result so far)
Support HiKey Fastboot driver for Fastboot App.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org --- .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c | 705 +++++++++++++++++++++ .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf | 61 ++ 2 files changed, 766 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf
diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c new file mode 100644 index 0000000..78e1d0d --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c @@ -0,0 +1,705 @@ +/** @file + + Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> + Copyright (c) 2015-2017, Linaro. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/* + Implementation of the Android Fastboot Platform protocol, to be used by the + Fastboot UEFI application, for Hisilicon HiKey platform. +*/ + +#include <Protocol/AndroidFastbootPlatform.h> +#include <Protocol/BlockIo.h> +#include <Protocol/DiskIo.h> +#include <Protocol/EraseBlock.h> +#include <Protocol/SimpleTextOut.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/DevicePathLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/PrintLib.h> +#include <Library/TimerLib.h> + +#include <Guid/HiKeyVariable.h> + +#define FLASH_DEVICE_PATH_SIZE(DevPath) ( GetDevicePathSize (DevPath) - \ + sizeof (EFI_DEVICE_PATH_PROTOCOL)) + +#define PARTITION_NAME_MAX_LENGTH 72/2 + +#define IS_ALPHA(Char) (((Char) <= L'z' && (Char) >= L'a') || \ + ((Char) <= L'Z' && (Char) >= L'Z')) +#define IS_HEXCHAR(Char) (((Char) <= L'9' && (Char) >= L'0') || \ + IS_ALPHA(Char)) + +#define SERIAL_NUMBER_LENGTH 16 +#define BOOT_DEVICE_LENGTH 16 + +#define HIKEY_ERASE_SIZE (16 * 1024 * 1024) +#define HIKEY_ERASE_BLOCKS (HIKEY_ERASE_SIZE / EFI_PAGE_SIZE) + +typedef struct _FASTBOOT_PARTITION_LIST { + LIST_ENTRY Link; + CHAR16 PartitionName[PARTITION_NAME_MAX_LENGTH]; + EFI_HANDLE PartitionHandle; + EFI_LBA Lba; +} FASTBOOT_PARTITION_LIST; + +STATIC LIST_ENTRY mPartitionListHead; + +STATIC EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *mTextOut; + +/* + Helper to free the partition list +*/ +STATIC +VOID +FreePartitionList ( + VOID + ) +{ + FASTBOOT_PARTITION_LIST *Entry; + FASTBOOT_PARTITION_LIST *NextEntry; + + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&mPartitionListHead); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + NextEntry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link); + + RemoveEntryList (&Entry->Link); + FreePool (Entry); + + Entry = NextEntry; + } +} +/* + Read the PartitionName fields from the GPT partition entries, putting them + into an allocated array that should later be freed. +*/ +STATIC +EFI_STATUS +ReadPartitionEntries ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + OUT EFI_PARTITION_ENTRY **PartitionEntries + ) +{ + UINTN EntrySize; + UINTN NumEntries; + UINTN BufferSize; + UINT32 MediaId; + EFI_PARTITION_TABLE_HEADER *GptHeader; + EFI_STATUS Status; + + MediaId = BlockIo->Media->MediaId; + + // + // Read size of Partition entry and number of entries from GPT header + // + + GptHeader = AllocatePool (BlockIo->Media->BlockSize); + if (GptHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 1, BlockIo->Media->BlockSize, (VOID *) GptHeader); + if (EFI_ERROR (Status)) { + return Status; + } + + // Check there is a GPT on the media + if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID || + GptHeader->MyLBA != 1) { + DEBUG ((DEBUG_ERROR, + "Fastboot platform: No GPT on flash. " + "Fastboot on Versatile Express does not support MBR.\n" + )); + return EFI_DEVICE_ERROR; + } + + EntrySize = GptHeader->SizeOfPartitionEntry; + NumEntries = GptHeader->NumberOfPartitionEntries; + + FreePool (GptHeader); + + ASSERT (EntrySize != 0); + ASSERT (NumEntries != 0); + + BufferSize = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media->BlockSize); + *PartitionEntries = AllocatePool (BufferSize); + if (PartitionEntries == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 2, BufferSize, (VOID *) *PartitionEntries); + if (EFI_ERROR (Status)) { + FreePool (PartitionEntries); + return Status; + } + + return Status; +} + + +/* + Initialise: Open the Android NVM device and find the partitions on it. Save them in + a list along with the "PartitionName" fields for their GPT entries. + We will use these partition names as the key in + HiKeyFastbootPlatformFlashPartition. +*/ +EFI_STATUS +HiKeyFastbootPlatformInit ( + VOID + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePathDup; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *NextNode; + HARDDRIVE_DEVICE_PATH *PartitionNode; + UINTN NumHandles; + EFI_HANDLE *AllHandles; + UINTN LoopIndex; + EFI_HANDLE FlashHandle; + EFI_BLOCK_IO_PROTOCOL *FlashBlockIo; + EFI_PARTITION_ENTRY *PartitionEntries; + FASTBOOT_PARTITION_LIST *Entry; + + InitializeListHead (&mPartitionListHead); + + Status = gBS->LocateProtocol (&gEfiSimpleTextOutProtocolGuid, NULL, (VOID **) &mTextOut); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "Fastboot platform: Couldn't open Text Output Protocol: %r\n", Status + )); + return Status; + } + + // + // Get EFI_HANDLES for all the partitions on the block devices pointed to by + // PcdFastbootFlashDevicePath, also saving their GPT partition labels. + // There's no way to find all of a device's children, so we get every handle + // in the system supporting EFI_BLOCK_IO_PROTOCOL and then filter out ones + // that don't represent partitions on the flash device. + // + + FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath)); + + // + // Open the Disk IO protocol on the flash device - this will be used to read + // partition names out of the GPT entries + // + // Create another device path pointer because LocateDevicePath will modify it. + FlashDevicePathDup = FlashDevicePath; + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePathDup, &FlashHandle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status)); + // Failing to locate partitions should not prevent to do other Android FastBoot actions + return EFI_SUCCESS; + } + + Status = gBS->OpenProtocol ( + FlashHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &FlashBlockIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fastboot platform: Couldn't open Android NVM device (status: %r)\n", Status)); + return EFI_DEVICE_ERROR; + } + + // Read the GPT partition entry array into memory so we can get the partition names + Status = ReadPartitionEntries (FlashBlockIo, &PartitionEntries); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Warning: Failed to read partitions from Android NVM device (status: %r)\n", Status)); + // Failing to locate partitions should not prevent to do other Android FastBoot actions + return EFI_SUCCESS; + } + + // Get every Block IO protocol instance installed in the system + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NumHandles, + &AllHandles + ); + ASSERT_EFI_ERROR (Status); + + // Filter out handles that aren't children of the flash device + for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) { + // Get the device path for the handle + Status = gBS->OpenProtocol ( + AllHandles[LoopIndex], + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + + // Check if it is a sub-device of the flash device + if (!CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) { + // Device path starts with path of flash device. Check it isn't the flash + // device itself. + NextNode = NextDevicePathNode (DevicePath); + if (IsDevicePathEndType (NextNode)) { + // Create entry + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); + if (Entry == NULL) { + Status = EFI_OUT_OF_RESOURCES; + FreePartitionList (); + goto Exit; + } + + // Copy handle and partition name + Entry->PartitionHandle = AllHandles[LoopIndex]; + StrCpy (Entry->PartitionName, L"ptable"); + InsertTailList (&mPartitionListHead, &Entry->Link); + continue; + } + + // Assert that this device path node represents a partition. + ASSERT (NextNode->Type == MEDIA_DEVICE_PATH && + NextNode->SubType == MEDIA_HARDDRIVE_DP); + + PartitionNode = (HARDDRIVE_DEVICE_PATH *) NextNode; + + // Assert that the partition type is GPT. ReadPartitionEntries checks for + // presence of a GPT, so we should never find MBR partitions. + // ("MBRType" is a misnomer - this field is actually called "Partition + // Format") + ASSERT (PartitionNode->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER); + + // The firmware may install a handle for "partition 0", representing the + // whole device. Ignore it. + if (PartitionNode->PartitionNumber == 0) { + continue; + } + + // + // Add the partition handle to the list + // + + // Create entry + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); + if (Entry == NULL) { + Status = EFI_OUT_OF_RESOURCES; + FreePartitionList (); + goto Exit; + } + + // Copy handle and partition name + Entry->PartitionHandle = AllHandles[LoopIndex]; + StrnCpy ( + Entry->PartitionName, + PartitionEntries[PartitionNode->PartitionNumber - 1].PartitionName, // Partition numbers start from 1. + PARTITION_NAME_MAX_LENGTH + ); + Entry->Lba = PartitionEntries[PartitionNode->PartitionNumber - 1].StartingLBA; + InsertTailList (&mPartitionListHead, &Entry->Link); + + // Print a debug message if the partition label is empty or looks like + // garbage. + if (!IS_ALPHA (Entry->PartitionName[0])) { + DEBUG ((DEBUG_ERROR, + "Warning: Partition %d doesn't seem to have a GPT partition label. " + "You won't be able to flash it with Fastboot.\n", + PartitionNode->PartitionNumber + )); + } + } + } + +Exit: + FreePool (PartitionEntries); + FreePool (FlashDevicePath); + FreePool (AllHandles); + return Status; + +} + +VOID +HiKeyFastbootPlatformUnInit ( + VOID + ) +{ + FreePartitionList (); +} + +EFI_STATUS +HiKeyFastbootPlatformFlashPartition ( + IN CHAR8 *PartitionName, + IN UINTN Size, + IN VOID *Image + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + UINT32 MediaId; + UINTN PartitionSize; + FASTBOOT_PARTITION_LIST *Entry; + CHAR16 PartitionNameUnicode[60]; + BOOLEAN PartitionFound; +#ifdef SPARSE_HEADER + SPARSE_HEADER *SparseHeader; + CHUNK_HEADER *ChunkHeader; + UINTN Offset = 0; + UINT32 Chunk, EntrySize, EntryOffset; + UINT32 *FillVal, TmpCount, FillBuf[1024]; +#else + UINT32 EntrySize, EntryOffset; +#endif + VOID *Buffer; + + + AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode); + + PartitionFound = FALSE; + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + // Search the partition list for the partition named by PartitionName + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { + PartitionFound = TRUE; + break; + } + + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); + } + if (!PartitionFound) { + return EFI_NOT_FOUND; + } + + Status = gBS->OpenProtocol ( + Entry->PartitionHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); + return EFI_NOT_FOUND; + } + +#ifdef SPARSE_HEADER + SparseHeader=(SPARSE_HEADER *)Image; + + if (SparseHeader->Magic == SPARSE_HEADER_MAGIC) { + DEBUG ((DEBUG_INFO, "Sparse Magic: 0x%x Major: %d Minor: %d fhs: %d chs: %d bs: %d tbs: %d tcs: %d checksum: %d \n", + SparseHeader->Magic, SparseHeader->MajorVersion, SparseHeader->MinorVersion, SparseHeader->FileHeaderSize, + SparseHeader->ChunkHeaderSize, SparseHeader->BlockSize, SparseHeader->TotalBlocks, + SparseHeader->TotalChunks, SparseHeader->ImageChecksum)); + if (SparseHeader->MajorVersion != 1) { + DEBUG ((DEBUG_ERROR, "Sparse image version %d.%d not supported.\n", + SparseHeader->MajorVersion, SparseHeader->MinorVersion)); + return EFI_INVALID_PARAMETER; + } + + Size = SparseHeader->BlockSize * SparseHeader->TotalBlocks; + } +#endif + + // Check image will fit on device + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; + if (PartitionSize < Size) { + DEBUG ((DEBUG_ERROR, "Partition not big enough.\n")); + DEBUG ((DEBUG_ERROR, "Partition Size:\t%ld\nImage Size:\t%ld\n", PartitionSize, Size)); + + return EFI_VOLUME_FULL; + } + + MediaId = BlockIo->Media->MediaId; + + Status = gBS->OpenProtocol ( + Entry->PartitionHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + +#ifdef SPARSE_HEADER + if (SparseHeader->Magic == SPARSE_HEADER_MAGIC) { + CHAR16 OutputString[64]; + UINTN ChunkPrintDensity = + SparseHeader->TotalChunks > 1600 ? SparseHeader->TotalChunks / 200 : 32; + + Image += SparseHeader->FileHeaderSize; + for (Chunk = 0; Chunk < SparseHeader->TotalChunks; Chunk++) { + UINTN WriteSize; + ChunkHeader = (CHUNK_HEADER *)Image; + + // Show progress. Don't do it for every packet as outputting text + // might be time consuming. ChunkPrintDensity is calculated to + // provide an update every half percent change for large + // downloads. + if (Chunk % ChunkPrintDensity == 0) { + UnicodeSPrint(OutputString, sizeof(OutputString), + L"\r%5d / %5d chunks written (%d%%)", Chunk, + SparseHeader->TotalChunks, + (Chunk * 100) / SparseHeader->TotalChunks); + mTextOut->OutputString(mTextOut, OutputString); + } + + DEBUG ((DEBUG_INFO, "Chunk #%d - Type: 0x%x Size: %d TotalSize: %d Offset %d\n", + (Chunk+1), ChunkHeader->ChunkType, ChunkHeader->ChunkSize, + ChunkHeader->TotalSize, Offset)); + Image += sizeof(CHUNK_HEADER); + WriteSize=(SparseHeader->BlockSize) * ChunkHeader->ChunkSize; + switch (ChunkHeader->ChunkType) { + case CHUNK_TYPE_RAW: + DEBUG ((DEBUG_INFO, "Writing %d at Offset %d\n", WriteSize, Offset)); + Status = DiskIo->WriteDisk (DiskIo, MediaId, Offset, WriteSize, Image); + if (EFI_ERROR (Status)) { + return Status; + } + Image+=WriteSize; + break; + case CHUNK_TYPE_FILL: + //Assume fillVal is 0, and we can skip here + FillVal = (UINT32 *)Image; + Image += sizeof(UINT32); + if (*FillVal != 0){ + mTextOut->OutputString(mTextOut, OutputString); + for(TmpCount = 0; TmpCount < 1024; TmpCount++){ + FillBuf[TmpCount] = *FillVal; + } + for (TmpCount= 0; TmpCount < WriteSize; TmpCount += sizeof(FillBuf)) { + if ((WriteSize - TmpCount) < sizeof(FillBuf)) { + Status = DiskIo->WriteDisk (DiskIo, MediaId, Offset + TmpCount, WriteSize - TmpCount, FillBuf); + } else { + Status = DiskIo->WriteDisk (DiskIo, MediaId, Offset + TmpCount, sizeof(FillBuf), FillBuf); + } + if (EFI_ERROR (Status)) { + return Status; + } + } + } + break; + case CHUNK_TYPE_DONT_CARE: + break; + case CHUNK_TYPE_CRC32: + break; + default: + DEBUG ((DEBUG_ERROR, "Unknown Chunk Type: 0x%x", ChunkHeader->ChunkType)); + return EFI_PROTOCOL_ERROR; + } + Offset += WriteSize; + } + + UnicodeSPrint(OutputString, sizeof(OutputString), + L"\r%5d / %5d chunks written (100%%)\r\n", + SparseHeader->TotalChunks, SparseHeader->TotalChunks); + mTextOut->OutputString(mTextOut, OutputString); + } else { +#endif + if (AsciiStrCmp (PartitionName, "ptable") == 0) { + Buffer = Image; + if (AsciiStrnCmp (Buffer, "ENTRYHDR", 8) != 0) { + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); + return EFI_UNSUPPORTED; + } + Buffer += 8; + if (AsciiStrnCmp (Buffer, "primary", 7) != 0) { + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); + return EFI_UNSUPPORTED; + } + Buffer += 8; + EntryOffset = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; + Buffer += 4; + EntrySize = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; + if ((EntrySize + 512) > Size) { + DEBUG ((DEBUG_ERROR, "Entry size doesn't match\n")); + return EFI_UNSUPPORTED; + } + Buffer = Image + 512; + Status = DiskIo->WriteDisk (DiskIo, MediaId, EntryOffset, EntrySize, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + Buffer = Image + 16 + 12; + if (AsciiStrnCmp (Buffer, "ENTRYHDR", 8) != 0) + return Status; + Buffer += 8; + if (AsciiStrnCmp (Buffer, "second", 6) != 0) + return Status; + Buffer += 8; + EntryOffset = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; + Buffer += 4; + EntrySize = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; + if ((EntrySize + 512) > Size) { + DEBUG ((DEBUG_ERROR, "Entry size doesn't match\n")); + return EFI_UNSUPPORTED; + } + Buffer = Image + 512; + Status = DiskIo->WriteDisk (DiskIo, MediaId, EntryOffset, EntrySize, Buffer); + } else { + Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image); + } + if (EFI_ERROR (Status)) { + return Status; + } +#ifdef SPARSE_HEADER + } +#endif + + BlockIo->FlushBlocks(BlockIo); + MicroSecondDelay (50000); + + return Status; +} + +EFI_STATUS +HiKeyFastbootPlatformErasePartition ( + IN CHAR8 *PartitionName + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +HiKeyFastbootPlatformGetVar ( + IN CHAR8 *Name, + OUT CHAR8 *Value + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINT64 PartitionSize; + FASTBOOT_PARTITION_LIST *Entry; + CHAR16 PartitionNameUnicode[60]; + BOOLEAN PartitionFound; + CHAR16 DataUnicode[17]; + UINTN VariableSize; + + if (!AsciiStrCmp (Name, "max-download-size")) { + AsciiStrCpy (Value, FixedPcdGetPtr (PcdArmFastbootFlashLimit)); + } else if (!AsciiStrCmp (Name, "product")) { + AsciiStrCpy (Value, FixedPcdGetPtr (PcdFirmwareVendor)); + } else if (!AsciiStrCmp (Name, "serialno")) { + VariableSize = 17 * sizeof (CHAR16); + Status = gRT->GetVariable ( + (CHAR16 *)L"SerialNo", + &gHiKeyVariableGuid, + NULL, + &VariableSize, + &DataUnicode + ); + if (EFI_ERROR (Status)) { + *Value = '\0'; + return EFI_NOT_FOUND; + } + DataUnicode[(VariableSize / sizeof(CHAR16)) - 1] = '\0'; + UnicodeStrToAsciiStr (DataUnicode, Value); + } else if ( !AsciiStrnCmp (Name, "partition-size", 14)) { + AsciiStrToUnicodeStr ((Name + 15), PartitionNameUnicode); + PartitionFound = FALSE; + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + // Search the partition list for the partition named by PartitionName + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { + PartitionFound = TRUE; + break; + } + + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); + } + if (!PartitionFound) { + *Value = '\0'; + return EFI_NOT_FOUND; + } + + Status = gBS->OpenProtocol ( + Entry->PartitionHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); + *Value = '\0'; + return EFI_NOT_FOUND; + } + + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; + DEBUG ((DEBUG_ERROR, "Fastboot platform: check for partition-size:%a 0X%llx\n", Name, PartitionSize )); + AsciiSPrint (Value, 12, "0x%llx", PartitionSize); + } else if ( !AsciiStrnCmp (Name, "partition-type", 14)) { + DEBUG ((DEBUG_ERROR, "Fastboot platform: check for partition-type:%a\n", (Name + 15) )); + if ( !AsciiStrnCmp ( (Name + 15) , "system", 6) || !AsciiStrnCmp ( (Name + 15) , "userdata", 8) + || !AsciiStrnCmp ( (Name + 15) , "cache", 5)) { + AsciiStrCpy (Value, "ext4"); + } else { + AsciiStrCpy (Value, "raw"); + } + } else { + *Value = '\0'; + } + return EFI_SUCCESS; +} + +EFI_STATUS +HiKeyFastbootPlatformOemCommand ( + IN CHAR8 *Command + ) +{ + if (AsciiStrCmp (Command, "Demonstrate") == 0) { + DEBUG ((DEBUG_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n")); + return EFI_SUCCESS; + } else { + DEBUG ((DEBUG_ERROR, + "HiKey: Unrecognised Fastboot OEM command: %s\n", + Command + )); + return EFI_NOT_FOUND; + } +} + +FASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = { + HiKeyFastbootPlatformInit, + HiKeyFastbootPlatformUnInit, + HiKeyFastbootPlatformFlashPartition, + HiKeyFastbootPlatformErasePartition, + HiKeyFastbootPlatformGetVar, + HiKeyFastbootPlatformOemCommand +}; + +EFI_STATUS +EFIAPI +HiKeyFastbootPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return gBS->InstallProtocolInterface ( + &ImageHandle, + &gAndroidFastbootPlatformProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPlatformProtocol + ); +} diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf new file mode 100644 index 0000000..8afd096 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf @@ -0,0 +1,61 @@ +#/** @file +# +# Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = HiKeyFastbootDxe + FILE_GUID = 8e335c38-c4e1-494e-8011-37a858d9763d + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HiKeyFastbootPlatformEntryPoint + +[Sources.common] + HiKeyFastbootDxe.c + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + MemoryAllocationLib + PcdLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + TimerLib + +[Protocols] + gAndroidFastbootPlatformProtocolGuid + gEfiBlockIoProtocolGuid + gEfiDiskIoProtocolGuid + gEfiSimpleTextOutProtocolGuid + gEfiEraseBlockProtocolGuid + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec + ArmPkg/ArmPkg.dec + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec + +[Guids] + gHiKeyVariableGuid + +[Pcd] + gArmPlatformTokenSpaceGuid.PcdFirmwareVendor + gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath + gHiKeyTokenSpaceGuid.PcdArmFastbootFlashLimit
Add the platform boot manager to boot Android Fastboot.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org --- OpenPlatformPkg.dec | 1 + .../Library/PlatformBootManagerLib/PlatformBm.c | 485 +++++++++++++++ .../Library/PlatformBootManagerLib/PlatformBm.h | 59 ++ .../PlatformBootManagerLib.inf | 88 +++ .../Library/PlatformBootManagerLib/QuietBoot.c | 680 +++++++++++++++++++++ 5 files changed, 1313 insertions(+) create mode 100644 Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c create mode 100644 Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.h create mode 100644 Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf create mode 100644 Platforms/Hisilicon/Library/PlatformBootManagerLib/QuietBoot.c
diff --git a/OpenPlatformPkg.dec b/OpenPlatformPkg.dec index 2db143d..e82b4d4 100644 --- a/OpenPlatformPkg.dec +++ b/OpenPlatformPkg.dec @@ -39,5 +39,6 @@ [PcdsFixedAtBuild] ## Indicates the size in MB for RAM disk. gOpenPlatformTokenSpaceGuid.PcdRamDiskMaxSize|0|UINT32|0x00000001 + gOpenPlatformTokenSpaceGuid.PcdAndroidFastbootFile|{ 0x2a, 0x50, 0x88, 0x95, 0x70, 0x53, 0xe3, 0x11, 0x86, 0x31, 0xd7, 0xc5, 0x95, 0x13, 0x64, 0xc8 }|VOID*|0x00000002
[PcdsFeatureFlag] diff --git a/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c b/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c new file mode 100644 index 0000000..03b764d --- /dev/null +++ b/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.c @@ -0,0 +1,485 @@ +/** @file + Implementation for PlatformBootManagerLib library class interfaces. + + Copyright (C) 2015-2016, Red Hat, Inc. + Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> + Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2016-2017, Linaro Ltd. All rights reserved.<BR> + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <Library/DevicePathLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiBootManagerLib.h> +#include <Library/UefiLib.h> +#include <Protocol/DevicePath.h> +#include <Protocol/GraphicsOutput.h> +#include <Protocol/LoadedImage.h> +#include <Guid/EventGroup.h> +#include <Guid/TtyTerm.h> + +#include "PlatformBm.h" + +#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) } + + +#pragma pack (1) +typedef struct { + VENDOR_DEVICE_PATH SerialDxe; + UART_DEVICE_PATH Uart; + VENDOR_DEFINED_DEVICE_PATH TermType; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_SERIAL_CONSOLE; +#pragma pack () + +#define SERIAL_DXE_FILE_GUID { \ + 0xD3987D4B, 0x971A, 0x435F, \ + { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \ + } + +STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = { + // + // VENDOR_DEVICE_PATH SerialDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + SERIAL_DXE_FILE_GUID + }, + + // + // UART_DEVICE_PATH Uart + // + { + { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) }, + 0, // Reserved + FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate + FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits + FixedPcdGet8 (PcdUartDefaultParity), // Parity + FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits + }, + + // + // VENDOR_DEFINED_DEVICE_PATH TermType + // + { + { + MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, + DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH) + } + // + // Guid to be filled in dynamically + // + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + + +#pragma pack (1) +typedef struct { + USB_CLASS_DEVICE_PATH Keyboard; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_USB_KEYBOARD; +#pragma pack () + +STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = { + // + // USB_CLASS_DEVICE_PATH Keyboard + // + { + { + MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, + DP_NODE_LEN (USB_CLASS_DEVICE_PATH) + }, + 0xFFFF, // VendorId: any + 0xFFFF, // ProductId: any + 3, // DeviceClass: HID + 1, // DeviceSubClass: boot + 1 // DeviceProtocol: keyboard + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + + +/** + Check if the handle satisfies a particular condition. + + @param[in] Handle The handle to check. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. + + @retval TRUE The condition is satisfied. + @retval FALSE Otherwise. This includes the case when the condition could not + be fully evaluated due to an error. +**/ +typedef +BOOLEAN +(EFIAPI *FILTER_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + + +/** + Process a handle. + + @param[in] Handle The handle to process. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. +**/ +typedef +VOID +(EFIAPI *CALLBACK_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + +/** + Locate all handles that carry the specified protocol, filter them with a + callback function, and pass each handle that passes the filter to another + callback. + + @param[in] ProtocolGuid The protocol to look for. + + @param[in] Filter The filter function to pass each handle to. If this + parameter is NULL, then all handles are processed. + + @param[in] Process The callback function to pass each handle to that + clears the filter. +**/ +STATIC +VOID +FilterAndProcess ( + IN EFI_GUID *ProtocolGuid, + IN FILTER_FUNCTION Filter OPTIONAL, + IN CALLBACK_FUNCTION Process + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles; + UINTN NoHandles; + UINTN Idx; + + Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid, + NULL /* SearchKey */, &NoHandles, &Handles); + if (EFI_ERROR (Status)) { + // + // This is not an error, just an informative condition. + // + DEBUG ((DEBUG_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid, + Status)); + return; + } + + ASSERT (NoHandles > 0); + for (Idx = 0; Idx < NoHandles; ++Idx) { + CHAR16 *DevicePathText; + STATIC CHAR16 Fallback[] = L"<device path unavailable>"; + + // + // The ConvertDevicePathToText() function handles NULL input transparently. + // + DevicePathText = ConvertDevicePathToText ( + DevicePathFromHandle (Handles[Idx]), + FALSE, // DisplayOnly + FALSE // AllowShortcuts + ); + if (DevicePathText == NULL) { + DevicePathText = Fallback; + } + + if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) { + Process (Handles[Idx], DevicePathText); + } + + if (DevicePathText != Fallback) { + FreePool (DevicePathText); + } + } + gBS->FreePool (Handles); +} + + +/** + This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the + handle, and adds it to ConOut and ErrOut. +**/ +STATIC +VOID +EFIAPI +AddOutput ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = DevicePathFromHandle (Handle); + if (DevicePath == NULL) { + DEBUG ((DEBUG_ERROR, "%a: %s: handle %p: device path not found\n", + __FUNCTION__, ReportText, Handle)); + return; + } + + Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + DEBUG ((DEBUG_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__, + ReportText)); +} + +STATIC +VOID +PlatformRegisterFvBootOption ( + EFI_GUID *FileGuid, + CHAR16 *Description, + UINT32 Attributes + ) +{ + EFI_STATUS Status; + INTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle); + ASSERT (DevicePath != NULL); + DevicePath = AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); + ASSERT (DevicePath != NULL); + + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + FreePool (DevicePath); + + BootOptions = EfiBootManagerGetLoadOptions ( + &BootOptionCount, LoadOptionTypeBoot + ); + + OptionIndex = EfiBootManagerFindLoadOption ( + &NewOption, BootOptions, BootOptionCount + ); + + if (OptionIndex == -1) { + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); + ASSERT_EFI_ERROR (Status); + } + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + + +STATIC +VOID +PlatformRegisterOptionsAndKeys ( + VOID + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Enter; + EFI_INPUT_KEY F2; + EFI_INPUT_KEY Esc; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + + // + // Register ENTER as CONTINUE key + // + Enter.ScanCode = SCAN_NULL; + Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; + Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + ASSERT_EFI_ERROR (Status); + + // + // Map F2 and ESC to Boot Manager Menu + // + F2.ScanCode = SCAN_F2; + F2.UnicodeChar = CHAR_NULL; + Esc.ScanCode = SCAN_ESC; + Esc.UnicodeChar = CHAR_NULL; + Status = EfiBootManagerGetBootManagerMenu (&BootOption); + ASSERT_EFI_ERROR (Status); + Status = EfiBootManagerAddKeyOptionVariable ( + NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL + ); + ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); + Status = EfiBootManagerAddKeyOptionVariable ( + NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL + ); + ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); +} + + +// +// BDS Platform Functions +// +/** + Do the platform init, can be customized by OEM/IBV + Possible things that can be done in PlatformBootManagerBeforeConsole: + > Update console variable: 1. include hot-plug devices; + > 2. Clear ConIn and add SOL for AMT + > Register new Driver#### or Boot#### + > Register new Key####: e.g.: F12 + > Signal ReadyToLock event + > Authentication action: 1. connect Auth devices; + > 2. Identify auto logon user. +**/ +VOID +EFIAPI +PlatformBootManagerBeforeConsole ( + VOID + ) +{ + // + // Signal EndOfDxe PI Event + // + EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); + + // + // Now add the device path of all handles with GOP on them to ConOut and + // ErrOut. + // + FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); + + // + // Add the hardcoded short-form USB keyboard device path to ConIn. + // + EfiBootManagerUpdateConsoleVariable (ConIn, + (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL); + + // + // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. + // + ASSERT (FixedPcdGet8 (PcdDefaultTerminalType) == 4); + CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid); + + EfiBootManagerUpdateConsoleVariable (ConIn, + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + EfiBootManagerUpdateConsoleVariable (ConOut, + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + + // + // Register platform-specific boot options and keyboard shortcuts. + // + PlatformRegisterOptionsAndKeys (); +} + +/** + Do the platform specific action after the console is ready + Possible things that can be done in PlatformBootManagerAfterConsole: + > Console post action: + > Dynamically switch output mode from 100x31 to 80x25 for certain senarino + > Signal console ready platform customized event + > Run diagnostics like memory testing + > Connect certain devices + > Dispatch aditional option roms + > Special boot: e.g.: USB boot, enter UI +**/ +VOID +EFIAPI +PlatformBootManagerAfterConsole ( + VOID + ) +{ + Print (L"Press ESCAPE for boot options "); + + // + // Show the splash screen. + // + EnableQuietBoot (PcdGetPtr (PcdLogoFile)); + + // + // Connect the rest of the devices. + // + EfiBootManagerConnectAll (); + + // + // Enumerate all possible boot options. + // + EfiBootManagerRefreshAllBootOption (); + + // + // Register UEFI Shell + // + PlatformRegisterFvBootOption ( + PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE + ); + + // + // Register Android Fastboot + // + PlatformRegisterFvBootOption ( + PcdGetPtr (PcdAndroidFastbootFile), L"Android Fastboot", LOAD_OPTION_ACTIVE + ); +} + +/** + This function is called each second during the boot manager waits the + timeout. + + @param TimeoutRemain The remaining timeout. +**/ +VOID +EFIAPI +PlatformBootManagerWaitCallback ( + UINT16 TimeoutRemain + ) +{ + Print (L"."); +} diff --git a/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.h b/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.h new file mode 100644 index 0000000..0a3c626 --- /dev/null +++ b/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBm.h @@ -0,0 +1,59 @@ +/** @file + Head file for BDS Platform specific code + + Copyright (C) 2015-2016, Red Hat, Inc. + Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR> + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PLATFORM_BM_H_ +#define _PLATFORM_BM_H_ + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/DevicePathLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> + +/** + Use SystemTable Conout to stop video based Simple Text Out consoles from + going to the video device. Put up LogoFile on every video device that is a + console. + + @param[in] LogoFile File name of logo to display on the center of the + screen. + + @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo + displayed. + @retval EFI_UNSUPPORTED Logo not found +**/ +EFI_STATUS +EnableQuietBoot ( + IN EFI_GUID *LogoFile + ); + +/** + Use SystemTable Conout to turn on video based Simple Text Out consoles. The + Simple Text Out screens will now be synced up with all non video output + devices + + @retval EFI_SUCCESS UGA devices are back in text mode and synced up. +**/ +EFI_STATUS +DisableQuietBoot ( + VOID + ); + +#endif // _PLATFORM_BM_H_ diff --git a/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf new file mode 100644 index 0000000..3256758 --- /dev/null +++ b/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -0,0 +1,88 @@ +## @file +# Implementation for PlatformBootManagerLib library class interfaces. +# +# Copyright (C) 2015-2016, Red Hat, Inc. +# Copyright (c) 2014, ARM Ltd. All rights reserved.<BR> +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR> +# Copyright (c) 2016-2017, Linaro Ltd. All rights reserved.<BR> +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR +# IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PlatformBootManagerLib + FILE_GUID = a5a1ecfc-7c11-427a-8803-012869067095 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = ARM AARCH64 +# + +[Sources] + PlatformBm.c + QuietBoot.c + +[Packages] + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OpenPlatformPkg/OpenPlatformPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + DxeServicesLib + MemoryAllocationLib + PcdLib + PrintLib + UefiBootManagerLib + UefiBootServicesTableLib + UefiLib + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdBootlogoOnlyEnable + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport + +[FixedPcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + gOpenPlatformTokenSpaceGuid.PcdAndroidFastbootFile + +[Guids] + gEfiFileInfoGuid + gEfiFileSystemInfoGuid + gEfiFileSystemVolumeLabelInfoIdGuid + gEfiEndOfDxeEventGroupGuid + gEfiTtyTermGuid + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiOEMBadgingProtocolGuid + gEfiPciRootBridgeIoProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiDevicePathToTextProtocolGuid diff --git a/Platforms/Hisilicon/Library/PlatformBootManagerLib/QuietBoot.c b/Platforms/Hisilicon/Library/PlatformBootManagerLib/QuietBoot.c new file mode 100644 index 0000000..687bda0 --- /dev/null +++ b/Platforms/Hisilicon/Library/PlatformBootManagerLib/QuietBoot.c @@ -0,0 +1,680 @@ +/** @file + Platform BDS function for quiet boot support. + +Copyright (C) 2016, Red Hat, Inc. +Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR> +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <IndustryStandard/Bmp.h> +#include <Library/DxeServicesLib.h> +#include <Protocol/BootLogo.h> +#include <Protocol/OEMBadging.h> +#include <Protocol/UgaDraw.h> + +#include "PlatformBm.h" + +/** + Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer + is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt + buffer is passed in it will be used if it is big enough. + + @param BmpImage Pointer to BMP file + @param BmpImageSize Number of bytes in BmpImage + @param GopBlt Buffer containing GOP version of BmpImage. + @param GopBltSize Size of GopBlt in bytes. + @param PixelHeight Height of GopBlt/BmpImage in pixels + @param PixelWidth Width of GopBlt/BmpImage in pixels + + @retval EFI_SUCCESS GopBlt and GopBltSize are returned. + @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image + @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough. + GopBltSize will contain the required size. + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate. + +**/ +STATIC +EFI_STATUS +ConvertBmpToGopBlt ( + IN VOID *BmpImage, + IN UINTN BmpImageSize, + IN OUT VOID **GopBlt, + IN OUT UINTN *GopBltSize, + OUT UINTN *PixelHeight, + OUT UINTN *PixelWidth + ) +{ + UINT8 *Image; + UINT8 *ImageHeader; + BMP_IMAGE_HEADER *BmpHeader; + BMP_COLOR_MAP *BmpColorMap; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; + UINT64 BltBufferSize; + UINTN Index; + UINTN Height; + UINTN Width; + UINTN ImageIndex; + UINT32 DataSizePerLine; + BOOLEAN IsAllocated; + UINT32 ColorMapNum; + + if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) { + return EFI_INVALID_PARAMETER; + } + + BmpHeader = (BMP_IMAGE_HEADER *) BmpImage; + + if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') { + return EFI_UNSUPPORTED; + } + + // + // Doesn't support compress. + // + if (BmpHeader->CompressionType != 0) { + return EFI_UNSUPPORTED; + } + + // + // Only support BITMAPINFOHEADER format. + // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER + // + if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) { + return EFI_UNSUPPORTED; + } + + // + // The data size in each line must be 4 byte alignment. + // + DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3); + BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight); + if (BltBufferSize > (UINT32) ~0) { + return EFI_INVALID_PARAMETER; + } + + if ((BmpHeader->Size != BmpImageSize) || + (BmpHeader->Size < BmpHeader->ImageOffset) || + (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) { + return EFI_INVALID_PARAMETER; + } + + // + // Calculate Color Map offset in the image. + // + Image = BmpImage; + BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER)); + if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) { + return EFI_INVALID_PARAMETER; + } + + if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) { + switch (BmpHeader->BitPerPixel) { + case 1: + ColorMapNum = 2; + break; + case 4: + ColorMapNum = 16; + break; + case 8: + ColorMapNum = 256; + break; + default: + ColorMapNum = 0; + break; + } + // + // BMP file may has padding data between the bmp header section and the bmp data section. + // + if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Calculate graphics image data address in the image + // + Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset; + ImageHeader = Image; + + // + // Calculate the BltBuffer needed size. + // + BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight); + // + // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow + // + if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { + return EFI_UNSUPPORTED; + } + BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + + IsAllocated = FALSE; + if (*GopBlt == NULL) { + // + // GopBlt is not allocated by caller. + // + *GopBltSize = (UINTN) BltBufferSize; + *GopBlt = AllocatePool (*GopBltSize); + IsAllocated = TRUE; + if (*GopBlt == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else { + // + // GopBlt has been allocated by caller. + // + if (*GopBltSize < (UINTN) BltBufferSize) { + *GopBltSize = (UINTN) BltBufferSize; + return EFI_BUFFER_TOO_SMALL; + } + } + + *PixelWidth = BmpHeader->PixelWidth; + *PixelHeight = BmpHeader->PixelHeight; + + // + // Convert image from BMP to Blt buffer format + // + BltBuffer = *GopBlt; + for (Height = 0; Height < BmpHeader->PixelHeight; Height++) { + Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth]; + for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) { + switch (BmpHeader->BitPerPixel) { + case 1: + // + // Convert 1-bit (2 colors) BMP to 24-bit color + // + for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) { + Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red; + Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green; + Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue; + Blt++; + Width++; + } + + Blt--; + Width--; + break; + + case 4: + // + // Convert 4-bit (16 colors) BMP Palette to 24-bit color + // + Index = (*Image) >> 4; + Blt->Red = BmpColorMap[Index].Red; + Blt->Green = BmpColorMap[Index].Green; + Blt->Blue = BmpColorMap[Index].Blue; + if (Width < (BmpHeader->PixelWidth - 1)) { + Blt++; + Width++; + Index = (*Image) & 0x0f; + Blt->Red = BmpColorMap[Index].Red; + Blt->Green = BmpColorMap[Index].Green; + Blt->Blue = BmpColorMap[Index].Blue; + } + break; + + case 8: + // + // Convert 8-bit (256 colors) BMP Palette to 24-bit color + // + Blt->Red = BmpColorMap[*Image].Red; + Blt->Green = BmpColorMap[*Image].Green; + Blt->Blue = BmpColorMap[*Image].Blue; + break; + + case 24: + // + // It is 24-bit BMP. + // + Blt->Blue = *Image++; + Blt->Green = *Image++; + Blt->Red = *Image; + break; + + default: + // + // Other bit format BMP is not supported. + // + if (IsAllocated) { + FreePool (*GopBlt); + *GopBlt = NULL; + } + return EFI_UNSUPPORTED; + }; + + } + + ImageIndex = (UINTN) (Image - ImageHeader); + if ((ImageIndex % 4) != 0) { + // + // Bmp Image starts each row on a 32-bit boundary! + // + Image = Image + (4 - (ImageIndex % 4)); + } + } + + return EFI_SUCCESS; +} + +/** + Use SystemTable Conout to stop video based Simple Text Out consoles from going + to the video device. Put up LogoFile on every video device that is a console. + + @param[in] LogoFile File name of logo to display on the center of the screen. + + @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo displayed. + @retval EFI_UNSUPPORTED Logo not found + +**/ +EFI_STATUS +EnableQuietBoot ( + IN EFI_GUID *LogoFile + ) +{ + EFI_STATUS Status; + EFI_OEM_BADGING_PROTOCOL *Badging; + UINT32 SizeOfX; + UINT32 SizeOfY; + INTN DestX; + INTN DestY; + UINT8 *ImageData; + UINTN ImageSize; + UINTN BltSize; + UINT32 Instance; + EFI_BADGING_FORMAT Format; + EFI_BADGING_DISPLAY_ATTRIBUTE Attribute; + UINTN CoordinateX; + UINTN CoordinateY; + UINTN Height; + UINTN Width; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + UINT32 ColorDepth; + UINT32 RefreshRate; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_BOOT_LOGO_PROTOCOL *BootLogo; + UINTN NumberOfLogos; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt; + UINTN LogoDestX; + UINTN LogoDestY; + UINTN LogoHeight; + UINTN LogoWidth; + UINTN NewDestX; + UINTN NewDestY; + UINTN NewHeight; + UINTN NewWidth; + UINT64 BufferSize; + + UgaDraw = NULL; + // + // Try to open GOP first + // + Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput); + if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) { + GraphicsOutput = NULL; + // + // Open GOP failed, try to open UGA + // + Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw); + } + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Try to open Boot Logo Protocol. + // + BootLogo = NULL; + gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); + + // + // Erase Cursor from screen + // + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + Badging = NULL; + Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging); + + if (GraphicsOutput != NULL) { + SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution; + SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution; + + } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + } else { + return EFI_UNSUPPORTED; + } + + Blt = NULL; + NumberOfLogos = 0; + LogoDestX = 0; + LogoDestY = 0; + LogoHeight = 0; + LogoWidth = 0; + NewDestX = 0; + NewDestY = 0; + NewHeight = 0; + NewWidth = 0; + Instance = 0; + Height = 0; + Width = 0; + while (1) { + ImageData = NULL; + ImageSize = 0; + + if (Badging != NULL) { + // + // Get image from OEMBadging protocol. + // + Status = Badging->GetImage ( + Badging, + &Instance, + &Format, + &ImageData, + &ImageSize, + &Attribute, + &CoordinateX, + &CoordinateY + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Currently only support BMP format. + // + if (Format != EfiBadgingFormatBMP) { + if (ImageData != NULL) { + FreePool (ImageData); + } + continue; + } + } else { + // + // Get the specified image from FV. + // + Status = GetSectionFromAnyFv (LogoFile, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + CoordinateX = 0; + CoordinateY = 0; + if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) { + Attribute = EfiBadgingDisplayAttributeCenter; + } else { + Attribute = EfiBadgingDisplayAttributeCustomized; + } + } + + if (Blt != NULL) { + FreePool (Blt); + } + Blt = NULL; + Status = ConvertBmpToGopBlt ( + ImageData, + ImageSize, + (VOID **) &Blt, + &BltSize, + &Height, + &Width + ); + if (EFI_ERROR (Status)) { + FreePool (ImageData); + + if (Badging == NULL) { + return Status; + } else { + continue; + } + } + + // + // Calculate the display position according to Attribute. + // + switch (Attribute) { + case EfiBadgingDisplayAttributeLeftTop: + DestX = CoordinateX; + DestY = CoordinateY; + break; + + case EfiBadgingDisplayAttributeCenterTop: + DestX = (SizeOfX - Width) / 2; + DestY = CoordinateY; + break; + + case EfiBadgingDisplayAttributeRightTop: + DestX = (SizeOfX - Width - CoordinateX); + DestY = CoordinateY;; + break; + + case EfiBadgingDisplayAttributeCenterRight: + DestX = (SizeOfX - Width - CoordinateX); + DestY = (SizeOfY - Height) / 2; + break; + + case EfiBadgingDisplayAttributeRightBottom: + DestX = (SizeOfX - Width - CoordinateX); + DestY = (SizeOfY - Height - CoordinateY); + break; + + case EfiBadgingDisplayAttributeCenterBottom: + DestX = (SizeOfX - Width) / 2; + DestY = (SizeOfY - Height - CoordinateY); + break; + + case EfiBadgingDisplayAttributeLeftBottom: + DestX = CoordinateX; + DestY = (SizeOfY - Height - CoordinateY); + break; + + case EfiBadgingDisplayAttributeCenterLeft: + DestX = CoordinateX; + DestY = (SizeOfY - Height) / 2; + break; + + case EfiBadgingDisplayAttributeCenter: + DestX = (SizeOfX - Width) / 2; + DestY = (SizeOfY - Height) / 2; + break; + + case EfiBadgingDisplayAttributeCustomized: + DestX = (SizeOfX - Width) / 2; + DestY = ((SizeOfY * 382) / 1000) - Height / 2; + break; + + default: + DestX = CoordinateX; + DestY = CoordinateY; + break; + } + + if ((DestX >= 0) && (DestY >= 0)) { + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + Blt, + EfiBltBufferToVideo, + 0, + 0, + (UINTN) DestX, + (UINTN) DestY, + Width, + Height, + Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) Blt, + EfiUgaBltBufferToVideo, + 0, + 0, + (UINTN) DestX, + (UINTN) DestY, + Width, + Height, + Width * sizeof (EFI_UGA_PIXEL) + ); + } else { + Status = EFI_UNSUPPORTED; + } + + // + // Report displayed Logo information. + // + if (!EFI_ERROR (Status)) { + NumberOfLogos++; + + if (LogoWidth == 0) { + // + // The first Logo. + // + LogoDestX = (UINTN) DestX; + LogoDestY = (UINTN) DestY; + LogoWidth = Width; + LogoHeight = Height; + } else { + // + // Merge new logo with old one. + // + NewDestX = MIN ((UINTN) DestX, LogoDestX); + NewDestY = MIN ((UINTN) DestY, LogoDestY); + NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX; + NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY; + + LogoDestX = NewDestX; + LogoDestY = NewDestY; + LogoWidth = NewWidth; + LogoHeight = NewHeight; + } + } + } + + FreePool (ImageData); + + if (Badging == NULL) { + break; + } + } + +Done: + if (BootLogo == NULL || NumberOfLogos == 0) { + // + // No logo displayed. + // + if (Blt != NULL) { + FreePool (Blt); + } + + return Status; + } + + // + // Advertise displayed Logo information. + // + if (NumberOfLogos == 1) { + // + // Only one logo displayed, use its Blt buffer directly for BootLogo protocol. + // + LogoBlt = Blt; + Status = EFI_SUCCESS; + } else { + // + // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation. + // + if (Blt != NULL) { + FreePool (Blt); + } + + // + // Ensure the LogoHeight * LogoWidth doesn't overflow + // + if (LogoHeight > DivU64x64Remainder ((UINTN) ~0, LogoWidth, NULL)) { + return EFI_UNSUPPORTED; + } + BufferSize = MultU64x64 (LogoWidth, LogoHeight); + + // + // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow + // + if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { + return EFI_UNSUPPORTED; + } + + LogoBlt = AllocateZeroPool ((UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + if (LogoBlt == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (GraphicsOutput != NULL) { + Status = GraphicsOutput->Blt ( + GraphicsOutput, + LogoBlt, + EfiBltVideoToBltBuffer, + LogoDestX, + LogoDestY, + 0, + 0, + LogoWidth, + LogoHeight, + LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) { + Status = UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) LogoBlt, + EfiUgaVideoToBltBuffer, + LogoDestX, + LogoDestY, + 0, + 0, + LogoWidth, + LogoHeight, + LogoWidth * sizeof (EFI_UGA_PIXEL) + ); + } else { + Status = EFI_UNSUPPORTED; + } + } + + if (!EFI_ERROR (Status)) { + BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight); + } + FreePool (LogoBlt); + + return Status; +} + +/** + Use SystemTable Conout to turn on video based Simple Text Out consoles. The + Simple Text Out screens will now be synced up with all non video output devices + + @retval EFI_SUCCESS UGA devices are back in text mode and synced up. + +**/ +EFI_STATUS +DisableQuietBoot ( + VOID + ) +{ + + // + // Enable Cursor on Screen + // + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_SUCCESS; +} +
Enable HiKeyGpio, HiKeyUsb and Platform Boot Manager to launch Android Fastboot App on HiKey platform.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang haojian.zhuang@linaro.org --- Platforms/Hisilicon/HiKey/HiKey.dsc | 18 ++++++++++++++++-- Platforms/Hisilicon/HiKey/HiKey.fdf | 6 +++++- 2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/Platforms/Hisilicon/HiKey/HiKey.dsc b/Platforms/Hisilicon/HiKey/HiKey.dsc index 492faaa..08e8d0a 100644 --- a/Platforms/Hisilicon/HiKey/HiKey.dsc +++ b/Platforms/Hisilicon/HiKey/HiKey.dsc @@ -62,7 +62,7 @@
FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf - PlatformBootManagerLib|ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf + PlatformBootManagerLib|OpenPlatformPkg/Platforms/Hisilicon/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf @@ -162,7 +162,7 @@ ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
[BuildOptions] - GCC:*_*_*_PLATFORM_FLAGS = -I$(WORKSPACE)/OpenPlatformPkg/Chips/Hisilicon/Hi6220/Include -I$(WORKSPACE)/OpenPlatformPkg/Platforms/Hisilicon/HiKey/Include + GCC:*_*_*_PLATFORM_FLAGS = -I$(WORKSPACE)/OpenPlatformPkg/Chips/Hisilicon/Hi6220/Include -I$(WORKSPACE)/OpenPlatformPkg/Platforms/Hisilicon/HiKey/Include -I$(WORKSPACE)/OpenPlatformPkg/Include
[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] GCC:*_*_AARCH64_DLINK_FLAGS = -z common-page-size=0x10000 @@ -339,11 +339,19 @@ gDwEmmcDxeTokenSpaceGuid.PcdDwEmmcDxeClockFrequencyInHz|100000000
# + # DW USB controller + # + gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0xF72C0000 + + # # # Fastboot # gEmbeddedTokenSpaceGuid.PcdAndroidFastbootUsbVendorId|0x18d1 gEmbeddedTokenSpaceGuid.PcdAndroidFastbootUsbProductId|0xd00d + gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L"VenHw(b549f005-4bd4-4020-a0cb-06f42bda68c3)" + # Flash limit 128M/time, for memory concern + gHiKeyTokenSpaceGuid.PcdArmFastbootFlashLimit|"134217728"
################################################################################ # @@ -396,6 +404,7 @@ # GPIO # ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf
# # MMC/SD @@ -417,6 +426,10 @@ # USB Peripheral Support # EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf + OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf +
# # Fastboot @@ -451,6 +464,7 @@ MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + FatPkg/EnhancedFatDxe/Fat.inf
# # Bds diff --git a/Platforms/Hisilicon/HiKey/HiKey.fdf b/Platforms/Hisilicon/HiKey/HiKey.fdf index 9c8c54a..280ec25 100644 --- a/Platforms/Hisilicon/HiKey/HiKey.fdf +++ b/Platforms/Hisilicon/HiKey/HiKey.fdf @@ -118,6 +118,7 @@ READ_LOCK_STATUS = TRUE # GPIO # INF ArmPlatformPkg/Drivers/PL061GpioDxe/PL061GpioDxe.inf + INF OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf
# # Multimedia Card Interface @@ -139,6 +140,9 @@ READ_LOCK_STATUS = TRUE # USB Peripheral Support # INF EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf + INF OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf + INF OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf + INF OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf
# # Fastboot @@ -168,7 +172,7 @@ READ_LOCK_STATUS = TRUE # INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf - INF FatBinPkg/EnhancedFatDxe/Fat.inf + INF FatPkg/EnhancedFatDxe/Fat.inf INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf