Platforms/Hisilicon/HiKey: support designware USB controller

Support Designware USB device controller on HiKey platform.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
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