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
HiKeyDetectUsbModeInit(IN 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
HiKeyGetUsbMode(IN VOID)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
HiKeyUsbPhyInit(IN UINT8 Mode)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
HiKeyUsbGetLang(OUT CHAR16 * Lang,OUT UINT8 * Length)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
HiKeyUsbGetManuFacturer(OUT CHAR16 * ManuFacturer,OUT UINT8 * Length)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
HiKeyUsbGetProduct(OUT CHAR16 * Product,OUT UINT8 * Length)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
HiKeyUsbGetSerialNo(OUT CHAR16 * SerialNo,OUT UINT8 * Length)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
HiKeyUsbEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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