• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 *
3 *  Copyright (c) 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/BlockIo.h>
26 #include <Protocol/DwUsb.h>
27 
28 #include <Hi3660.h>
29 
30 #define USB_EYE_PARAM                  0x01c466e3
31 #define USB_PHY_TX_VBOOST_LVL          5
32 
33 #define DWC3_PHY_RX_OVRD_IN_HI         0x1006
34 #define DWC3_PHY_RX_SCOPE_VDCC         0x1026
35 
36 #define RX_SCOPE_LFPS_EN               (1 << 0)
37 
38 #define TX_VBOOST_LVL_MASK             7
39 #define TX_VBOOST_LVL(x)               ((x) & TX_VBOOST_LVL_MASK)
40 
41 #define SERIAL_NUMBER_LBA              20
42 
43 STATIC EFI_HANDLE mFlashHandle;
44 
45 UINTN
HiKey960GetUsbMode(IN VOID)46 HiKey960GetUsbMode (
47   IN VOID
48   )
49 {
50   return USB_DEVICE_MODE;
51 }
52 
53 VOID
HiKey960UsbPhyCrWaitAck(VOID)54 HiKey960UsbPhyCrWaitAck (
55   VOID
56   )
57 {
58   INT32                Timeout = 1000;
59   UINT32               Data;
60 
61   while (TRUE) {
62     Data = MmioRead32 (USB3OTG_PHY_CR_STS);
63     if ((Data & USB3OTG_PHY_CR_ACK) == USB3OTG_PHY_CR_ACK) {
64       return;
65     }
66     MicroSecondDelay (50);
67     if (Timeout-- <= 0) {
68       DEBUG ((DEBUG_ERROR, "Wait PHY_CR_ACK timeout!\n"));
69       return;
70     }
71   }
72 }
73 
74 VOID
HiKey960UsbPhyCrSetAddr(IN UINT32 Addr)75 HiKey960UsbPhyCrSetAddr (
76   IN UINT32            Addr
77   )
78 {
79   // set addr
80   MmioWrite32 (
81     USB3OTG_PHY_CR_CTRL,
82     USB3OTG_PHY_CR_DATA_IN (Addr)
83     );
84   MicroSecondDelay (100);
85   // cap addr
86   MmioOr32 (USB3OTG_PHY_CR_CTRL, USB3OTG_PHY_CR_CAP_ADDR);
87   HiKey960UsbPhyCrWaitAck ();
88   MmioWrite32 (USB3OTG_PHY_CR_CTRL, 0);
89 }
90 
91 UINT16
HiKey960UsbPhyCrRead(IN UINT32 Addr)92 HiKey960UsbPhyCrRead (
93   IN UINT32            Addr
94   )
95 {
96   INT32                Timeout = 1000;
97   UINT32               Data;
98 
99   HiKey960UsbPhyCrSetAddr (Addr);
100   MmioWrite32 (USB3OTG_PHY_CR_CTRL, USB3OTG_PHY_CR_READ);
101   MicroSecondDelay (100);
102 
103   while (TRUE) {
104     Data = MmioRead32 (USB3OTG_PHY_CR_STS);
105     if ((Data & USB3OTG_PHY_CR_ACK) == USB3OTG_PHY_CR_ACK) {
106       DEBUG ((
107         DEBUG_INFO,
108         "Addr 0x%x, Data Out:0x%x\n",
109         Addr,
110         USB3OTG_PHY_CR_DATA_OUT(Data)
111         ));
112       break;
113     }
114     MicroSecondDelay (50);
115     if (Timeout-- <= 0) {
116       DEBUG ((DEBUG_ERROR, "Wait PHY_CR_ACK timeout!\n"));
117       break;
118     }
119   }
120   MmioWrite32 (USB3OTG_PHY_CR_CTRL, 0);
121   return (UINT16)USB3OTG_PHY_CR_DATA_OUT(Data);
122 }
123 
124 VOID
HiKey960UsbPhyCrWrite(IN UINT32 Addr,IN UINT32 Value)125 HiKey960UsbPhyCrWrite (
126   IN UINT32            Addr,
127   IN UINT32            Value
128   )
129 {
130   UINT32               Data;
131 
132   HiKey960UsbPhyCrSetAddr (Addr);
133   Data = USB3OTG_PHY_CR_DATA_IN(Value);
134   MmioWrite32 (USB3OTG_PHY_CR_CTRL, Data);
135 
136   Data = MmioRead32 (USB3OTG_PHY_CR_CTRL);
137   Data |= USB3OTG_PHY_CR_CAP_DATA;
138   MmioWrite32 (USB3OTG_PHY_CR_CTRL, Data);
139   HiKey960UsbPhyCrWaitAck ();
140 
141   MmioWrite32 (USB3OTG_PHY_CR_CTRL, 0);
142   MmioWrite32 (USB3OTG_PHY_CR_CTRL, USB3OTG_PHY_CR_WRITE);
143   HiKey960UsbPhyCrWaitAck ();
144 }
145 
146 VOID
HiKey960UsbSetEyeDiagramParam(VOID)147 HiKey960UsbSetEyeDiagramParam (
148   VOID
149   )
150 {
151   UINT32               Data;
152 
153   /* set eye diagram for usb 2.0 */
154   MmioWrite32 (USB3OTG_CTRL4, USB_EYE_PARAM);
155   /* set eye diagram for usb 3.0 */
156   HiKey960UsbPhyCrRead (DWC3_PHY_RX_OVRD_IN_HI);
157   HiKey960UsbPhyCrWrite (DWC3_PHY_RX_OVRD_IN_HI, BIT11 | BIT9 | BIT8 |BIT7);
158   HiKey960UsbPhyCrRead (DWC3_PHY_RX_OVRD_IN_HI);
159 
160   /* enable RX_SCOPE_LFPS_EN for usb 3.0 */
161   Data = HiKey960UsbPhyCrRead (DWC3_PHY_RX_SCOPE_VDCC);
162   Data |= RX_SCOPE_LFPS_EN;
163   HiKey960UsbPhyCrWrite (DWC3_PHY_RX_SCOPE_VDCC, Data);
164   HiKey960UsbPhyCrRead (DWC3_PHY_RX_SCOPE_VDCC);
165 
166   Data = MmioRead32 (USB3OTG_CTRL6);
167   Data &= ~TX_VBOOST_LVL_MASK;
168   Data = TX_VBOOST_LVL (USB_PHY_TX_VBOOST_LVL);
169   MmioWrite32 (USB3OTG_CTRL6, Data);
170   DEBUG ((
171     DEBUG_INFO,
172     "set ss phy tx vboost lvl 0x%x\n",
173     MmioRead32 (USB3OTG_CTRL6)
174     ));
175 }
176 
177 STATIC
178 VOID
HiKey960UsbReset(VOID)179 HiKey960UsbReset (
180   VOID
181   )
182 {
183   MmioWrite32 (CRG_PERRSTEN4, PERRSTEN4_USB3OTG);
184   MmioWrite32 (CRG_PERRSTEN4, PERRSTEN4_USB3OTGPHY_POR);
185   MmioWrite32 (
186     CRG_PERRSTEN4,
187     PERRSTEN4_USB3OTG_MUX | PERRSTEN4_USB3OTG_AHBIF | PERRSTEN4_USB3OTG_32K
188     );
189   MmioWrite32 (
190     CRG_PERDIS4,
191     PEREN4_GT_ACLK_USB3OTG | PEREN4_GT_CLK_USB3OTG_REF
192     );
193 
194   MmioAnd32 (PCTRL_CTRL24, ~PCTRL_CTRL24_USB3PHY_3MUX1_SEL);
195   // disable
196   MmioWrite32 (PCTRL_CTRL3, (PCTRL_CTRL3_USB_TXCO_EN << 16) | 0);
197   MicroSecondDelay (10000);
198 }
199 
200 STATIC
201 VOID
HiKey960UsbRelease(VOID)202 HiKey960UsbRelease (
203   VOID
204   )
205 {
206   /* enable USB REFCLK ISO */
207   MmioWrite32 (CRG_ISODIS, PERISOEN_USB_REFCLK_ISO_EN);
208   /* enable USB_TXCO_EN */
209   MmioWrite32 (PCTRL_CTRL3, (PCTRL_CTRL3_USB_TXCO_EN << 16) | PCTRL_CTRL3_USB_TXCO_EN);
210 
211   MmioAnd32 (PCTRL_CTRL24, ~PCTRL_CTRL24_USB3PHY_3MUX1_SEL);
212 
213   MmioWrite32 (
214     CRG_PEREN4,
215     PEREN4_GT_ACLK_USB3OTG | PEREN4_GT_CLK_USB3OTG_REF
216     );
217   MmioWrite32 (
218     CRG_PERRSTDIS4,
219     PERRSTEN4_USB3OTG_MUX | PERRSTEN4_USB3OTG_AHBIF | PERRSTEN4_USB3OTG_32K
220     );
221 
222   MmioWrite32 (CRG_PERRSTEN4, PERRSTEN4_USB3OTG | PERRSTEN4_USB3OTGPHY_POR);
223 
224   /* enable PHY REF CLK */
225   MmioOr32 (USB3OTG_CTRL0, USB3OTG_CTRL0_SC_USB3PHY_ABB_GT_EN);
226 
227   MmioOr32 (USB3OTG_CTRL7, USB3OTG_CTRL7_REF_SSP_EN);
228 
229   /* exit from IDDQ mode */
230   MmioAnd32 (
231     USB3OTG_CTRL2,
232     ~(USB3OTG_CTRL2_TEST_POWERDOWN_SSP | USB3OTG_CTRL2_TEST_POWERDOWN_HSP)
233     );
234   MicroSecondDelay (100000);
235 
236   MmioWrite32 (CRG_PERRSTDIS4, PERRSTEN4_USB3OTGPHY_POR);
237   MmioWrite32 (CRG_PERRSTDIS4, PERRSTEN4_USB3OTG);
238   MicroSecondDelay (10000);
239   MmioOr32 (USB3OTG_CTRL3, USB3OTG_CTRL3_VBUSVLDEXT | USB3OTG_CTRL3_VBUSVLDEXTSEL);
240   MicroSecondDelay (100000);
241 
242   HiKey960UsbSetEyeDiagramParam ();
243 }
244 
245 EFI_STATUS
HiKey960UsbPhyInit(IN UINT8 Mode)246 HiKey960UsbPhyInit (
247   IN UINT8        Mode
248   )
249 {
250   HiKey960UsbReset ();
251   MicroSecondDelay (10000);
252   HiKey960UsbRelease ();
253 
254   return EFI_SUCCESS;
255 }
256 
257 EFI_STATUS
258 EFIAPI
HiKey960UsbGetLang(OUT CHAR16 * Lang,OUT UINT8 * Length)259 HiKey960UsbGetLang (
260   OUT CHAR16            *Lang,
261   OUT UINT8             *Length
262   )
263 {
264   if ((Lang == NULL) || (Length == NULL)) {
265     return EFI_INVALID_PARAMETER;
266   }
267   Lang[0] = 0x409;
268   *Length = sizeof (CHAR16);
269   return EFI_SUCCESS;
270 }
271 
272 EFI_STATUS
273 EFIAPI
HiKey960UsbGetManuFacturer(OUT CHAR16 * ManuFacturer,OUT UINT8 * Length)274 HiKey960UsbGetManuFacturer (
275   OUT CHAR16            *ManuFacturer,
276   OUT UINT8             *Length
277   )
278 {
279   UINTN                  VariableSize;
280   CHAR16                 DataUnicode[MANU_FACTURER_STRING_LENGTH];
281 
282   if ((ManuFacturer == NULL) || (Length == NULL)) {
283     return EFI_INVALID_PARAMETER;
284   }
285   VariableSize = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16);
286   ZeroMem (DataUnicode, MANU_FACTURER_STRING_LENGTH * sizeof(CHAR16));
287   StrCpy (DataUnicode, L"96Boards");
288   CopyMem (ManuFacturer, DataUnicode, VariableSize);
289   *Length = VariableSize;
290   return EFI_SUCCESS;
291 }
292 
293 EFI_STATUS
294 EFIAPI
HiKey960UsbGetProduct(OUT CHAR16 * Product,OUT UINT8 * Length)295 HiKey960UsbGetProduct (
296   OUT CHAR16            *Product,
297   OUT UINT8             *Length
298   )
299 {
300   UINTN                  VariableSize;
301   CHAR16                 DataUnicode[PRODUCT_STRING_LENGTH];
302 
303   if ((Product == NULL) || (Length == NULL)) {
304     return EFI_INVALID_PARAMETER;
305   }
306   VariableSize = PRODUCT_STRING_LENGTH * sizeof (CHAR16);
307   ZeroMem (DataUnicode, PRODUCT_STRING_LENGTH * sizeof(CHAR16));
308   StrCpy (DataUnicode, L"HiKey960");
309   CopyMem (Product, DataUnicode, VariableSize);
310   *Length = VariableSize;
311   return EFI_SUCCESS;
312 }
313 
314 EFI_STATUS
315 EFIAPI
HiKey960UsbGetSerialNo(OUT CHAR16 * SerialNo,OUT UINT8 * Length)316 HiKey960UsbGetSerialNo (
317   OUT CHAR16            *SerialNo,
318   OUT UINT8             *Length
319   )
320 {
321   EFI_STATUS                          Status;
322   EFI_DEVICE_PATH_PROTOCOL           *FlashDevicePath;
323 
324   if (mFlashHandle == 0) {
325     FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath));
326     Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePath, &mFlashHandle);
327     if (EFI_ERROR (Status)) {
328       DEBUG ((DEBUG_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status));
329       // Failing to locate partitions should not prevent to do other Android FastBoot actions
330       return EFI_SUCCESS;
331     }
332   }
333 
334   if ((SerialNo == NULL) || (Length == NULL)) {
335     return EFI_INVALID_PARAMETER;
336   }
337   Status = LoadSNFromBlock (mFlashHandle, SERIAL_NUMBER_LBA, SerialNo);
338   *Length = StrSize (SerialNo);
339   return Status;
340 }
341 
342 DW_USB_PROTOCOL mDwUsbDevice = {
343   HiKey960UsbGetLang,
344   HiKey960UsbGetManuFacturer,
345   HiKey960UsbGetProduct,
346   HiKey960UsbGetSerialNo,
347   HiKey960UsbPhyInit
348 };
349 
350 EFI_STATUS
351 EFIAPI
HiKey960UsbEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)352 HiKey960UsbEntryPoint (
353   IN EFI_HANDLE                            ImageHandle,
354   IN EFI_SYSTEM_TABLE                      *SystemTable
355   )
356 {
357   return gBS->InstallProtocolInterface (
358                 &ImageHandle,
359                 &gDwUsbProtocolGuid,
360                 EFI_NATIVE_INTERFACE,
361                 &mDwUsbDevice
362                 );
363 }
364