1 /** @file 2 * 3 * Copyright (c) 2015-2017, Linaro. All rights reserved. 4 * 5 * This program and the accompanying materials 6 * are licensed and made available under the terms and conditions of the BSD License 7 * which accompanies this distribution. The full text of the license may be found at 8 * http://opensource.org/licenses/bsd-license.php 9 * 10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 * 13 **/ 14 15 #include <Library/BaseMemoryLib.h> 16 #include <Library/DebugLib.h> 17 #include <Library/DevicePathLib.h> 18 #include <Library/IoLib.h> 19 #include <Library/TimerLib.h> 20 #include <Library/UefiBootServicesTableLib.h> 21 #include <Library/UefiLib.h> 22 #include <Library/UefiRuntimeServicesTableLib.h> 23 #include <Library/UsbSerialNumberLib.h> 24 25 #include <Protocol/EmbeddedGpio.h> 26 #include <Protocol/DwUsb.h> 27 28 #include <Hi6220.h> 29 30 31 #define USB_SEL_GPIO0_3 3 // GPIO 0_3 32 #define USB_5V_HUB_EN 7 // GPIO 0_7 33 #define USB_ID_DET_GPIO2_5 21 // GPIO 2_5 34 #define USB_VBUS_DET_GPIO2_6 22 // GPIO 2_6 35 36 // Jumper on pin5-6 of J15 determines whether boot to fastboot 37 #define DETECT_J15_FASTBOOT 24 // GPIO 3_0 38 39 #define SERIAL_NUMBER_LBA 1024 40 41 STATIC EMBEDDED_GPIO *mGpio; 42 43 STATIC 44 VOID 45 HiKeyDetectUsbModeInit ( 46 IN VOID 47 ) 48 { 49 EFI_STATUS Status; 50 51 /* set pullup on both GPIO2_5 & GPIO2_6. It's required for inupt. */ 52 MmioWrite32 (0xf8001864, 1); 53 MmioWrite32 (0xf8001868, 1); 54 55 Status = gBS->LocateProtocol (&gEmbeddedGpioProtocolGuid, NULL, (VOID **)&mGpio); 56 ASSERT_EFI_ERROR (Status); 57 Status = mGpio->Set (mGpio, USB_SEL_GPIO0_3, GPIO_MODE_OUTPUT_0); 58 ASSERT_EFI_ERROR (Status); 59 Status = mGpio->Set (mGpio, USB_5V_HUB_EN, GPIO_MODE_OUTPUT_0); 60 ASSERT_EFI_ERROR (Status); 61 MicroSecondDelay (1000); 62 63 Status = mGpio->Set (mGpio, USB_ID_DET_GPIO2_5, GPIO_MODE_INPUT); 64 ASSERT_EFI_ERROR (Status); 65 Status = mGpio->Set (mGpio, USB_VBUS_DET_GPIO2_6, GPIO_MODE_INPUT); 66 ASSERT_EFI_ERROR (Status); 67 } 68 69 UINTN 70 HiKeyGetUsbMode ( 71 IN VOID 72 ) 73 { 74 #if 0 75 EFI_STATUS Status; 76 UINTN GpioId, GpioVbus; 77 UINTN Value; 78 79 Status = mGpio->Get (mGpio, USB_ID_DET_GPIO2_5, &Value); 80 ASSERT_EFI_ERROR (Status); 81 GpioId = Value; 82 Status = mGpio->Get (mGpio, USB_VBUS_DET_GPIO2_6, &Value); 83 ASSERT_EFI_ERROR (Status); 84 GpioVbus = Value; 85 86 DEBUG ((DEBUG_ERROR, "#%a, %d, GpioId:%d, GpioVbus:%d\n", __func__, __LINE__, GpioId, GpioVbus)); 87 if ((GpioId == 1) && (GpioVbus == 0)) { 88 return USB_DEVICE_MODE; 89 } else if ((GpioId == 0) && (GpioVbus == 1)) { 90 return USB_CABLE_NOT_ATTACHED; 91 } 92 return USB_HOST_MODE; 93 #else 94 return USB_DEVICE_MODE; 95 #endif 96 } 97 98 EFI_STATUS 99 HiKeyUsbPhyInit ( 100 IN UINT8 Mode 101 ) 102 { 103 UINTN Value; 104 UINT32 Data; 105 106 HiKeyDetectUsbModeInit (); 107 108 //setup clock 109 MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN0, BIT4); 110 do { 111 Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CLKSTAT0); 112 } while ((Value & BIT4) == 0); 113 114 //setup phy 115 Data = RST0_USBOTG_BUS | RST0_POR_PICOPHY | 116 RST0_USBOTG | RST0_USBOTG_32K; 117 MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS0, Data); 118 do { 119 Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_RSTSTAT0); 120 Value &= Data; 121 } while (Value); 122 123 Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4); 124 Value &= ~(CTRL4_PICO_SIDDQ | CTRL4_FPGA_EXT_PHY_SEL | 125 CTRL4_OTG_PHY_SEL); 126 Value |= CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL; 127 MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4, Value); 128 MicroSecondDelay (1000); 129 130 //If Mode = 1, USB in Device Mode 131 //If Mode = 0, USB in Host Mode 132 if (Mode == USB_DEVICE_MODE) { 133 if (HiKeyGetUsbMode () == USB_DEVICE_MODE) { 134 DEBUG ((DEBUG_ERROR, "usb work as device mode.\n")); 135 } else { 136 return EFI_INVALID_PARAMETER; 137 } 138 139 Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5); 140 Value &= ~CTRL5_PICOPHY_BC_MODE; 141 MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Value); 142 MicroSecondDelay (20000); 143 } else { 144 if (HiKeyGetUsbMode () == USB_HOST_MODE) { 145 DEBUG ((DEBUG_ERROR, "usb work as host mode.\n")); 146 } else { 147 return EFI_INVALID_PARAMETER; 148 } 149 150 /*CTRL5*/ 151 Data = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5); 152 Data &= ~CTRL5_PICOPHY_BC_MODE; 153 Data |= CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB | 154 CTRL5_PICOPHY_VDATDETENB | CTRL5_PICOPHY_DCDENB; 155 MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Data); 156 MicroSecondDelay (20000); 157 MmioWrite32 (PERI_CTRL_BASE + 0x018, 0x70533483); //EYE_PATTERN 158 159 MicroSecondDelay (5000); 160 } 161 162 return EFI_SUCCESS; 163 } 164 165 EFI_STATUS 166 EFIAPI 167 HiKeyUsbGetLang ( 168 OUT CHAR16 *Lang, 169 OUT UINT8 *Length 170 ) 171 { 172 if ((Lang == NULL) || (Length == NULL)) { 173 return EFI_INVALID_PARAMETER; 174 } 175 Lang[0] = 0x409; 176 *Length = sizeof (CHAR16); 177 return EFI_SUCCESS; 178 } 179 180 EFI_STATUS 181 EFIAPI 182 HiKeyUsbGetManuFacturer ( 183 OUT CHAR16 *ManuFacturer, 184 OUT UINT8 *Length 185 ) 186 { 187 UINTN VariableSize; 188 CHAR16 DataUnicode[MANU_FACTURER_STRING_LENGTH]; 189 190 if ((ManuFacturer == NULL) || (Length == NULL)) { 191 return EFI_INVALID_PARAMETER; 192 } 193 VariableSize = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16); 194 ZeroMem (DataUnicode, MANU_FACTURER_STRING_LENGTH * sizeof(CHAR16)); 195 StrCpy (DataUnicode, L"96Boards"); 196 CopyMem (ManuFacturer, DataUnicode, VariableSize); 197 *Length = VariableSize; 198 return EFI_SUCCESS; 199 } 200 201 EFI_STATUS 202 EFIAPI 203 HiKeyUsbGetProduct ( 204 OUT CHAR16 *Product, 205 OUT UINT8 *Length 206 ) 207 { 208 UINTN VariableSize; 209 CHAR16 DataUnicode[PRODUCT_STRING_LENGTH]; 210 211 if ((Product == NULL) || (Length == NULL)) { 212 return EFI_INVALID_PARAMETER; 213 } 214 VariableSize = PRODUCT_STRING_LENGTH * sizeof (CHAR16); 215 ZeroMem (DataUnicode, PRODUCT_STRING_LENGTH * sizeof(CHAR16)); 216 StrCpy (DataUnicode, L"HiKey"); 217 CopyMem (Product, DataUnicode, VariableSize); 218 *Length = VariableSize; 219 return EFI_SUCCESS; 220 } 221 222 EFI_STATUS 223 EFIAPI 224 HiKeyUsbGetSerialNo ( 225 OUT CHAR16 *SerialNo, 226 OUT UINT8 *Length 227 ) 228 { 229 EFI_STATUS Status; 230 EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath; 231 EFI_HANDLE FlashHandle; 232 233 FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath)); 234 Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePath, &FlashHandle); 235 if (EFI_ERROR (Status)) { 236 DEBUG ((DEBUG_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status)); 237 // Failing to locate partitions should not prevent to do other Android FastBoot actions 238 return EFI_SUCCESS; 239 } 240 241 if ((SerialNo == NULL) || (Length == NULL)) { 242 return EFI_INVALID_PARAMETER; 243 } 244 Status = LoadSNFromBlock (FlashHandle, SERIAL_NUMBER_LBA, SerialNo); 245 *Length = StrSize (SerialNo); 246 return Status; 247 } 248 249 DW_USB_PROTOCOL mDwUsbDevice = { 250 HiKeyUsbGetLang, 251 HiKeyUsbGetManuFacturer, 252 HiKeyUsbGetProduct, 253 HiKeyUsbGetSerialNo, 254 HiKeyUsbPhyInit 255 }; 256 257 EFI_STATUS 258 EFIAPI 259 HiKeyUsbEntryPoint ( 260 IN EFI_HANDLE ImageHandle, 261 IN EFI_SYSTEM_TABLE *SystemTable 262 ) 263 { 264 EFI_STATUS Status; 265 266 Status = gBS->InstallProtocolInterface ( 267 &ImageHandle, 268 &gDwUsbProtocolGuid, 269 EFI_NATIVE_INTERFACE, 270 &mDwUsbDevice 271 ); 272 if (EFI_ERROR (Status)) { 273 return Status; 274 } 275 return Status; 276 } 277