• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host controller
3   MMIO base, to upper layer UFS drivers.
4 
5   Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
6   Copyright (c) 2016 - 2017, Linaro Ltd. All rights reserved.
7 
8   This program and the accompanying materials
9   are licensed and made available under the terms and conditions of the BSD License
10   which accompanies this distribution.  The full text of the license may be found at
11   http://opensource.org/licenses/bsd-license.php.
12 
13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 
16 **/
17 
18 #include "DwUfsHcDxe.h"
19 
20 #include <IndustryStandard/Pci.h>
21 
22 #include <Protocol/PciIo.h>
23 
24 //
25 // Ufs Host Controller Driver Binding Protocol Instance
26 //
27 EFI_DRIVER_BINDING_PROTOCOL gUfsHcDriverBinding = {
28   UfsHcDriverBindingSupported,
29   UfsHcDriverBindingStart,
30   UfsHcDriverBindingStop,
31   0x10,
32   NULL,
33   NULL
34 };
35 
36 //
37 // Template for Ufs host controller private data.
38 //
39 UFS_HOST_CONTROLLER_PRIVATE_DATA gUfsHcTemplate = {
40   UFS_HC_PRIVATE_DATA_SIGNATURE,  // Signature
41   NULL,                           // Handle
42   {                               // UfsHcProtocol
43     UfsHcGetMmioBar,
44     UfsHcAllocateBuffer,
45     UfsHcFreeBuffer,
46     UfsHcMap,
47     UfsHcUnmap,
48     UfsHcFlush,
49     UfsHcMmioRead,
50     UfsHcMmioWrite,
51     UfsHcPhyInit,
52     UfsHcPhySetPowerMode,
53   },
54   0                               // RegBase
55 };
56 
57 STATIC
58 EFI_STATUS
DwUfsDmeSet(IN UINTN RegBase,IN UINT16 Attr,IN UINT16 Index,IN UINT32 Value)59 DwUfsDmeSet (
60   IN  UINTN         RegBase,
61   IN  UINT16        Attr,
62   IN  UINT16        Index,
63   IN  UINT32        Value
64   )
65 {
66   UINT32            Data;
67 
68   Data = MmioRead32 (RegBase + UFS_HC_STATUS_OFFSET);
69   if ((Data & UFS_HC_HCS_UCRDY) == 0) {
70     return EFI_NOT_READY;
71   }
72   MmioWrite32 (RegBase + UFS_HC_IS_OFFSET, ~0);
73   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG1_OFFSET, (Attr << 16) | Index);
74   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG2_OFFSET, 0);
75   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG3_OFFSET, Value);
76   MmioWrite32 (RegBase + UFS_HC_UIC_CMD_OFFSET, UFS_UIC_DME_SET);
77   do {
78     Data = MmioRead32 (RegBase + UFS_HC_IS_OFFSET);
79     if (Data & UFS_HC_IS_UE) {
80       return EFI_DEVICE_ERROR;
81     }
82   } while ((Data & UFS_HC_IS_UCCS) == 0);
83   MmioWrite32 (RegBase + UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS);
84   Data = MmioRead32 (RegBase + UFS_HC_UCMD_ARG2_OFFSET);
85   if (Data) {
86     return EFI_DEVICE_ERROR;
87   }
88   return EFI_SUCCESS;
89 }
90 
91 STATIC
92 EFI_STATUS
DwUfsDmeGet(IN UINTN RegBase,IN UINT16 Attr,IN UINT16 Index,OUT UINT32 * Value)93 DwUfsDmeGet (
94   IN  UINTN         RegBase,
95   IN  UINT16        Attr,
96   IN  UINT16        Index,
97   OUT UINT32        *Value
98   )
99 {
100   UINT32            Data;
101 
102   Data = MmioRead32 (RegBase + UFS_HC_STATUS_OFFSET);
103   if ((Data & UFS_HC_HCS_UCRDY) == 0) {
104     return EFI_NOT_READY;
105   }
106   MmioWrite32 (RegBase + UFS_HC_IS_OFFSET, ~0);
107   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG1_OFFSET, (Attr << 16) | Index);
108   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG2_OFFSET, 0);
109   MmioWrite32 (RegBase + UFS_HC_UCMD_ARG3_OFFSET, 0);
110   MmioWrite32 (RegBase + UFS_HC_UIC_CMD_OFFSET, UFS_UIC_DME_GET);
111   do {
112     Data = MmioRead32 (RegBase + UFS_HC_IS_OFFSET);
113     if (Data & UFS_HC_IS_UE) {
114       return EFI_DEVICE_ERROR;
115     }
116   } while ((Data & UFS_HC_IS_UCCS) == 0);
117   MmioWrite32 (RegBase + UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS);
118   Data = MmioRead32 (RegBase + UFS_HC_UCMD_ARG2_OFFSET);
119   if (Data) {
120     return EFI_DEVICE_ERROR;
121   }
122   *Value = MmioRead32 (RegBase + UFS_HC_UCMD_ARG3_OFFSET);
123   return EFI_SUCCESS;
124 }
125 
126 /**
127   Get the MMIO base of the UFS host controller.
128 
129   @param[in]   This             A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
130   @param[out]  MmioBar          The MMIO base address of UFS host controller.
131 
132   @retval EFI_SUCCESS           The operation succeeds.
133   @retval others                The operation fails.
134 **/
135 EFI_STATUS
136 EFIAPI
UfsHcGetMmioBar(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This,OUT UINTN * MmioBar)137 UfsHcGetMmioBar (
138   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
139      OUT UINTN                              *MmioBar
140   )
141 {
142   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
143 
144   if ((This == NULL) || (MmioBar == NULL)) {
145     return EFI_INVALID_PARAMETER;
146   }
147 
148   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
149   *MmioBar = Private->RegBase;
150   return EFI_SUCCESS;
151 }
152 
153 /**
154   Provides the UFS controller-specific addresses needed to access system memory.
155 
156   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
157   @param  Operation             Indicates if the bus master is going to read or write to system memory.
158   @param  HostAddress           The system memory address to map to the UFS controller.
159   @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
160                                 that were mapped.
161   @param  DeviceAddress         The resulting map address for the bus master UFS controller to use to
162                                 access the hosts HostAddress.
163   @param  Mapping               A resulting value to pass to Unmap().
164 
165   @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
166   @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
167   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
168   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
169   @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
170 
171 **/
172 EFI_STATUS
173 EFIAPI
UfsHcMap(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This,IN EDKII_UFS_HOST_CONTROLLER_OPERATION Operation,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)174 UfsHcMap (
175   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *This,
176   IN     EDKII_UFS_HOST_CONTROLLER_OPERATION  Operation,
177   IN     VOID                                 *HostAddress,
178   IN OUT UINTN                                *NumberOfBytes,
179      OUT EFI_PHYSICAL_ADDRESS                 *DeviceAddress,
180      OUT VOID                                 **Mapping
181   )
182 {
183   DMA_MAP_OPERATION   DmaOperation;
184 
185   if ((This == NULL) || (HostAddress == NULL) || (NumberOfBytes == NULL) || (DeviceAddress == NULL) || (Mapping == NULL)) {
186     return EFI_INVALID_PARAMETER;
187   }
188 
189   if (Operation == EdkiiUfsHcOperationBusMasterRead) {
190     DmaOperation = MapOperationBusMasterRead;
191   } else if (Operation == EdkiiUfsHcOperationBusMasterWrite) {
192     DmaOperation = MapOperationBusMasterWrite;
193   } else if (Operation == EdkiiUfsHcOperationBusMasterCommonBuffer) {
194     DmaOperation = MapOperationBusMasterCommonBuffer;
195   } else {
196     return EFI_INVALID_PARAMETER;
197   }
198 
199   if ((*NumberOfBytes & (BIT0 | BIT1)) != 0) {
200     *NumberOfBytes += BIT0 | BIT1;
201     *NumberOfBytes &= ~(BIT0 | BIT1);
202   }
203 
204   return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
205 }
206 
207 /**
208   Completes the Map() operation and releases any corresponding resources.
209 
210   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
211   @param  Mapping               The mapping value returned from Map().
212 
213   @retval EFI_SUCCESS           The range was unmapped.
214   @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
215 
216 **/
217 EFI_STATUS
218 EFIAPI
UfsHcUnmap(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This,IN VOID * Mapping)219 UfsHcUnmap (
220   IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
221   IN  VOID                               *Mapping
222   )
223 {
224   if ((This == NULL) || (Mapping == NULL)) {
225     return EFI_INVALID_PARAMETER;
226   }
227 
228   return DmaUnmap (Mapping);
229 }
230 
231 /**
232   Allocates pages that are suitable for an EfiUfsHcOperationBusMasterCommonBuffer
233   mapping.
234 
235   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
236   @param  Type                  This parameter is not used and must be ignored.
237   @param  MemoryType            The type of memory to allocate, EfiBootServicesData or
238                                 EfiRuntimeServicesData.
239   @param  Pages                 The number of pages to allocate.
240   @param  HostAddress           A pointer to store the base system memory address of the
241                                 allocated range.
242   @param  Attributes            The requested bit mask of attributes for the allocated range.
243 
244   @retval EFI_SUCCESS           The requested memory pages were allocated.
245   @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
246                                 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
247   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
248   @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
249 
250 **/
251 EFI_STATUS
252 EFIAPI
UfsHcAllocateBuffer(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,OUT VOID ** HostAddress,IN UINT64 Attributes)253 UfsHcAllocateBuffer (
254   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
255   IN     EFI_ALLOCATE_TYPE                  Type,
256   IN     EFI_MEMORY_TYPE                    MemoryType,
257   IN     UINTN                              Pages,
258      OUT VOID                               **HostAddress,
259   IN     UINT64                             Attributes
260   )
261 {
262   if ((This == NULL) || (HostAddress == NULL)) {
263     return EFI_INVALID_PARAMETER;
264   }
265 
266   return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
267 }
268 
269 /**
270   Frees memory that was allocated with AllocateBuffer().
271 
272   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
273   @param  Pages                 The number of pages to free.
274   @param  HostAddress           The base system memory address of the allocated range.
275 
276   @retval EFI_SUCCESS           The requested memory pages were freed.
277   @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
278                                 was not allocated with AllocateBuffer().
279 
280 **/
281 EFI_STATUS
282 EFIAPI
UfsHcFreeBuffer(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This,IN UINTN Pages,IN VOID * HostAddress)283 UfsHcFreeBuffer (
284   IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
285   IN  UINTN                              Pages,
286   IN  VOID                               *HostAddress
287   )
288 {
289   if ((This == NULL) || (HostAddress == NULL)) {
290     return EFI_INVALID_PARAMETER;
291   }
292 
293   return DmaFreeBuffer (Pages, HostAddress);
294 }
295 
296 /**
297   Flushes all posted write transactions from the UFS bus to attached UFS device.
298 
299   @param  This                  A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
300 
301   @retval EFI_SUCCESS           The posted write transactions were flushed from the UFS bus
302                                 to attached UFS device.
303   @retval EFI_DEVICE_ERROR      The posted write transactions were not flushed from the UFS
304                                 bus to attached UFS device due to a hardware error.
305 
306 **/
307 EFI_STATUS
308 EFIAPI
UfsHcFlush(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This)309 UfsHcFlush (
310   IN  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
311   )
312 {
313   ArmInstructionSynchronizationBarrier ();
314   ArmDataSynchronizationBarrier ();
315   return EFI_SUCCESS;
316 }
317 
318 /**
319   Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space.
320 
321   @param  This                  A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance.
322   @param  Width                 Signifies the width of the memory operations.
323   @param  Offset                The offset within the UFS Host Controller MMIO space to start the
324                                 memory operation.
325   @param  Count                 The number of memory operations to perform.
326   @param  Buffer                For read operations, the destination buffer to store the results.
327                                 For write operations, the source buffer to write data from.
328 
329   @retval EFI_SUCCESS           The data was read from or written to the UFS host controller.
330   @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
331                                 valid for the UFS Host Controller memory space.
332   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
333   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
334 
335 **/
336 EFI_STATUS
337 EFIAPI
UfsHcMmioRead(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This,IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH Width,IN UINT64 Offset,IN UINTN Count,IN OUT VOID * Buffer)338 UfsHcMmioRead (
339   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL        *This,
340   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH  Width,
341   IN     UINT64                                    Offset,
342   IN     UINTN                                     Count,
343   IN OUT VOID                                      *Buffer
344   )
345 {
346   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
347   UINTN                             Index;
348 
349   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
350 
351   switch (Width) {
352   case EfiUfsHcWidthUint8:
353     for (Index = 0; Index < Count; Index++) {
354       *((UINT8 *)Buffer + Index) = MmioRead8 (Private->RegBase + Offset);
355     }
356     break;
357   case EfiUfsHcWidthUint16:
358     for (Index = 0; Index < Count; Index++) {
359       *((UINT16 *)Buffer + Index) = MmioRead16 (Private->RegBase + Offset);
360     }
361     break;
362   case EfiUfsHcWidthUint32:
363     for (Index = 0; Index < Count; Index++) {
364       *((UINT32 *)Buffer + Index) = MmioRead32 (Private->RegBase + Offset);
365     }
366     break;
367   case EfiUfsHcWidthUint64:
368     for (Index = 0; Index < Count; Index++) {
369       *((UINT64 *)Buffer + Index) = MmioRead64 (Private->RegBase + Offset);
370     }
371     break;
372   default:
373     return EFI_INVALID_PARAMETER;
374   }
375 
376   return EFI_SUCCESS;
377 }
378 
379 /**
380   Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space.
381 
382   @param  This                  A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance.
383   @param  Width                 Signifies the width of the memory operations.
384   @param  Offset                The offset within the UFS Host Controller MMIO space to start the
385                                 memory operation.
386   @param  Count                 The number of memory operations to perform.
387   @param  Buffer                For read operations, the destination buffer to store the results.
388                                 For write operations, the source buffer to write data from.
389 
390   @retval EFI_SUCCESS           The data was read from or written to the UFS host controller.
391   @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
392                                 valid for the UFS Host Controller memory space.
393   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
394   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
395 
396 **/
397 EFI_STATUS
398 EFIAPI
UfsHcMmioWrite(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This,IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH Width,IN UINT64 Offset,IN UINTN Count,IN OUT VOID * Buffer)399 UfsHcMmioWrite (
400   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL        *This,
401   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH  Width,
402   IN     UINT64                                    Offset,
403   IN     UINTN                                     Count,
404   IN OUT VOID                                      *Buffer
405   )
406 {
407   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
408   EFI_STATUS                        Status = EFI_SUCCESS;
409   UINTN                             Index;
410 
411   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
412 
413   switch (Width) {
414   case EfiUfsHcWidthUint8:
415     for (Index = 0; Index < Count; Index++) {
416       Status = MmioWrite8 (Private->RegBase + Offset, *((UINT8 *)Buffer + Index));
417     }
418     break;
419   case EfiUfsHcWidthUint16:
420     for (Index = 0; Index < Count; Index++) {
421       Status = MmioWrite16 (Private->RegBase + Offset, *((UINT16 *)Buffer + Index));
422     }
423     break;
424   case EfiUfsHcWidthUint32:
425     for (Index = 0; Index < Count; Index++) {
426       Status = MmioWrite32 (Private->RegBase + Offset, *((UINT32 *)Buffer + Index));
427     }
428     break;
429   case EfiUfsHcWidthUint64:
430     for (Index = 0; Index < Count; Index++) {
431       Status = MmioWrite64 (Private->RegBase + Offset, *((UINT64 *)Buffer + Index));
432     }
433     break;
434   default:
435     return EFI_INVALID_PARAMETER;
436   }
437 
438   return Status;
439 }
440 
441 EFI_STATUS
442 EFIAPI
UfsHcPhyInit(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This)443 UfsHcPhyInit (
444   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL        *This
445   )
446 {
447   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
448   EFI_STATUS                        Status;
449   UINT32                            Data, Fsm0, Fsm1;
450 
451   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
452   DwUfsDmeSet (Private->RegBase, 0xd0c1, 0, 1);
453   DwUfsDmeSet (Private->RegBase, 0xd0c1, 0, 1);
454   DwUfsDmeSet (Private->RegBase, 0x156a, 0, 2);
455   DwUfsDmeSet (Private->RegBase, 0x8114, 0, 1);
456   DwUfsDmeSet (Private->RegBase, 0x8121, 0, 0x2d);
457   DwUfsDmeSet (Private->RegBase, 0x8122, 0, 1);
458   DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1);
459   DwUfsDmeSet (Private->RegBase, 0x800d, 4, 0x58);
460   DwUfsDmeSet (Private->RegBase, 0x800d, 5, 0x58);
461   DwUfsDmeSet (Private->RegBase, 0x800e, 4, 0xb);
462   DwUfsDmeSet (Private->RegBase, 0x800e, 5, 0xb);
463   DwUfsDmeSet (Private->RegBase, 0x8009, 4, 0x1);
464   DwUfsDmeSet (Private->RegBase, 0x8009, 5, 0x1);
465   DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1);
466   DwUfsDmeSet (Private->RegBase, 0x8113, 0, 1);
467   DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1);
468   DwUfsDmeSet (Private->RegBase, 0x0095, 4, 0x4a);
469   DwUfsDmeSet (Private->RegBase, 0x0095, 5, 0x4a);
470   DwUfsDmeSet (Private->RegBase, 0x0094, 4, 0x4a);
471   DwUfsDmeSet (Private->RegBase, 0x0094, 5, 0x4a);
472   DwUfsDmeSet (Private->RegBase, 0x008f, 4, 0x7);
473   DwUfsDmeSet (Private->RegBase, 0x008f, 5, 0x7);
474   DwUfsDmeSet (Private->RegBase, 0x000f, 0, 0x5);
475   DwUfsDmeSet (Private->RegBase, 0x000f, 1, 0x5);
476   DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1);
477 
478   Status = DwUfsDmeGet (Private->RegBase, 0xd0c1, 0, &Data);
479   ASSERT_EFI_ERROR (Status);
480   ASSERT (Data == 1);
481 
482   DwUfsDmeSet (Private->RegBase, 0xd0c1, 0, 0);
483   for (;;) {
484     Status = DwUfsDmeGet (Private->RegBase, 0x0041, 0, &Fsm0);
485     ASSERT_EFI_ERROR (Status);
486     Status = DwUfsDmeGet (Private->RegBase, 0x0041, 1, &Fsm1);
487     ASSERT_EFI_ERROR (Status);
488     if ((Fsm0 == 1) && (Fsm1 == 1)) {
489       break;
490     }
491   }
492 
493   MmioWrite32 (Private->RegBase + UFS_HC_HCLKDIV_OFFSET, 0xE4);
494   Data = MmioRead32 (Private->RegBase + UFS_HC_AHIT_OFFSET);
495   Data &= ~0x3FF;
496   MmioWrite32 (Private->RegBase + UFS_HC_AHIT_OFFSET, Data);
497 
498   DwUfsDmeSet (Private->RegBase, 0x155e, 0, 0);
499   DwUfsDmeSet (Private->RegBase, 0xd0ab, 0, 0);
500 
501   Status = DwUfsDmeGet (Private->RegBase, 0xd0ab, 0, &Data);
502   ASSERT_EFI_ERROR ((Status) && (Data == 0));
503 
504   DwUfsDmeSet (Private->RegBase, 0x2044, 0, 0);
505   DwUfsDmeSet (Private->RegBase, 0x2045, 0, 0);
506   DwUfsDmeSet (Private->RegBase, 0x2040, 0, 9);
507   return EFI_SUCCESS;
508 }
509 
510 EFI_STATUS
511 EFIAPI
UfsHcPhySetPowerMode(IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL * This,IN UINT32 DevQuirks)512 UfsHcPhySetPowerMode (
513   IN     EDKII_UFS_HOST_CONTROLLER_PROTOCOL        *This,
514   IN     UINT32                                    DevQuirks
515   )
516 {
517   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
518   UINT32                            Data, TxLanes, RxLanes;
519 
520   Private  = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
521 
522   if (DevQuirks & UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME) {
523     DEBUG ((DEBUG_INFO | DEBUG_LOAD, "ufs: H**** device must set VS_DebugSaveConfigTime 0x10\n"));
524     /* VS_DebugSaveConfigTime */
525     DwUfsDmeSet (Private->RegBase, 0xD0A0, 0x0, 0x10);
526     /* sync length */
527     DwUfsDmeSet (Private->RegBase, 0x1556, 0x0, 0x48);
528   }
529 
530   // PA_Tactive
531   DwUfsDmeGet (Private->RegBase, 0x15A8, 0, &Data);
532   if (Data < 7) {
533     DwUfsDmeSet (Private->RegBase, 0x15A8, 4, 7);
534   }
535   DwUfsDmeGet (Private->RegBase, 0x1561, 0, &TxLanes);
536   DwUfsDmeGet (Private->RegBase, 0x1581, 0, &RxLanes);
537 
538   // PA TxSkip
539   DwUfsDmeSet (Private->RegBase, 0x155C, 0, 0);
540   // PA TxGear
541   DwUfsDmeSet (Private->RegBase, 0x1568, 0, 3);
542   // PA RxGear
543   DwUfsDmeSet (Private->RegBase, 0x1583, 0, 3);
544   // PA HSSeries
545   DwUfsDmeSet (Private->RegBase, 0x156A, 0, 2);
546   // PA TxTermination
547   DwUfsDmeSet (Private->RegBase, 0x1569, 0, 1);
548   // PA RxTermination
549   DwUfsDmeSet (Private->RegBase, 0x1584, 0, 1);
550   // PA Scrambling
551   DwUfsDmeSet (Private->RegBase, 0x1585, 0, 0);
552   // PA ActiveTxDataLines
553   DwUfsDmeSet (Private->RegBase, 0x1560, 0, TxLanes);
554   // PA ActiveRxDataLines
555   DwUfsDmeSet (Private->RegBase, 0x1580, 0, RxLanes);
556   // PA_PWRModeUserData0 = 8191
557   DwUfsDmeSet (Private->RegBase, 0x15B0, 0, 8191);
558   // PA_PWRModeUserData1 = 65535
559   DwUfsDmeSet (Private->RegBase, 0x15B1, 0, 65535);
560   // PA_PWRModeUserData2 = 32767
561   DwUfsDmeSet (Private->RegBase, 0x15B2, 0, 32767);
562   // DME_FC0ProtectionTimeOutVal = 8191
563   DwUfsDmeSet (Private->RegBase, 0xD041, 0, 8191);
564   // DME_TC0ReplayTimeOutVal = 65535
565   DwUfsDmeSet (Private->RegBase, 0xD042, 0, 65535);
566   // DME_AFC0ReqTimeOutVal = 32767
567   DwUfsDmeSet (Private->RegBase, 0xD043, 0, 32767);
568   // PA_PWRModeUserData3 = 8191
569   DwUfsDmeSet (Private->RegBase, 0x15B3, 0, 8191);
570   // PA_PWRModeUserData4 = 65535
571   DwUfsDmeSet (Private->RegBase, 0x15B4, 0, 65535);
572   // PA_PWRModeUserData5 = 32767
573   DwUfsDmeSet (Private->RegBase, 0x15B5, 0, 32767);
574   // DME_FC1ProtectionTimeOutVal = 8191
575   DwUfsDmeSet (Private->RegBase, 0xD044, 0, 8191);
576   // DME_TC1ReplayTimeOutVal = 65535
577   DwUfsDmeSet (Private->RegBase, 0xD045, 0, 65535);
578   // DME_AFC1ReqTimeOutVal = 32767
579   DwUfsDmeSet (Private->RegBase, 0xD046, 0, 32767);
580 
581   DwUfsDmeSet (Private->RegBase, 0x1571, 0, 0x11);
582   do {
583     Data = MmioRead32(Private->RegBase + UFS_HC_IS_OFFSET);
584   } while ((Data & UFS_INT_UPMS) == 0);
585   MmioWrite32(Private->RegBase + UFS_HC_IS_OFFSET, UFS_INT_UPMS);
586   Data = MmioRead32(Private->RegBase + UFS_HC_STATUS_OFFSET);
587   if ((Data & HCS_UPMCRS_MASK) == HCS_PWR_LOCAL) {
588     DEBUG ((DEBUG_INFO, "ufs: change power mode success\n"));
589   } else {
590     DEBUG ((DEBUG_ERROR, "ufs: HCS.UPMCRS error, HCS:0x%x\n", Data));
591   }
592   return EFI_SUCCESS;
593 }
594 
595 /**
596   Tests to see if this driver supports a given controller. If a child device is provided,
597   it further tests to see if this driver supports creating a handle for the specified child device.
598 
599   This function checks to see if the driver specified by This supports the device specified by
600   ControllerHandle. Drivers will typically use the device path attached to
601   ControllerHandle and/or the services from the bus I/O abstraction attached to
602   ControllerHandle to determine if the driver supports ControllerHandle. This function
603   may be called many times during platform initialization. In order to reduce boot times, the tests
604   performed by this function must be very small, and take as little time as possible to execute. This
605   function must not change the state of any hardware devices, and this function must be aware that the
606   device specified by ControllerHandle may already be managed by the same driver or a
607   different driver. This function must match its calls to AllocatePages() with FreePages(),
608   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
609   Since ControllerHandle may have been previously started by the same driver, if a protocol is
610   already in the opened state, then it must not be closed with CloseProtocol(). This is required
611   to guarantee the state of ControllerHandle is not modified by this function.
612 
613   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
614   @param[in]  ControllerHandle     The handle of the controller to test. This handle
615                                    must support a protocol interface that supplies
616                                    an I/O abstraction to the driver.
617   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
618                                    parameter is ignored by device drivers, and is optional for bus
619                                    drivers. For bus drivers, if this parameter is not NULL, then
620                                    the bus driver must determine if the bus controller specified
621                                    by ControllerHandle and the child controller specified
622                                    by RemainingDevicePath are both supported by this
623                                    bus driver.
624 
625   @retval EFI_SUCCESS              The device specified by ControllerHandle and
626                                    RemainingDevicePath is supported by the driver specified by This.
627   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
628                                    RemainingDevicePath is already being managed by the driver
629                                    specified by This.
630   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
631                                    RemainingDevicePath is already being managed by a different
632                                    driver or an application that requires exclusive access.
633                                    Currently not implemented.
634   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
635                                    RemainingDevicePath is not supported by the driver specified by This.
636 **/
637 EFI_STATUS
638 EFIAPI
UfsHcDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)639 UfsHcDriverBindingSupported (
640   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
641   IN EFI_HANDLE                   Controller,
642   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
643   )
644 {
645   EFI_STATUS                Status;
646   BOOLEAN                   UfsHcFound;
647   EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath = NULL;
648   EFI_PCI_IO_PROTOCOL       *PciIo = NULL;
649   PCI_TYPE00                PciData;
650 
651   ParentDevicePath = NULL;
652   UfsHcFound       = FALSE;
653 
654   //
655   // UfsHcDxe is a device driver, and should ingore the
656   // "RemainingDevicePath" according to EFI spec
657   //
658   Status = gBS->OpenProtocol (
659                   Controller,
660                   &gEfiDevicePathProtocolGuid,
661                   (VOID *) &ParentDevicePath,
662                   This->DriverBindingHandle,
663                   Controller,
664                   EFI_OPEN_PROTOCOL_BY_DRIVER
665                   );
666   if (EFI_ERROR (Status)) {
667     //
668     // EFI_ALREADY_STARTED is also an error
669     //
670     return Status;
671   }
672   //
673   // Close the protocol because we don't use it here
674   //
675   gBS->CloseProtocol (
676         Controller,
677         &gEfiDevicePathProtocolGuid,
678         This->DriverBindingHandle,
679         Controller
680         );
681 
682   //
683   // Now test the EfiPciIoProtocol
684   //
685   Status = gBS->OpenProtocol (
686                   Controller,
687                   &gEfiPciIoProtocolGuid,
688                   (VOID **) &PciIo,
689                   This->DriverBindingHandle,
690                   Controller,
691                   EFI_OPEN_PROTOCOL_BY_DRIVER
692                   );
693   if (EFI_ERROR (Status)) {
694     return Status;
695   }
696   //
697   // Now further check the PCI header: Base class (offset 0x0B) and
698   // Sub Class (offset 0x0A). This controller should be an UFS controller
699   //
700   Status = PciIo->Pci.Read (
701                         PciIo,
702                         EfiPciIoWidthUint8,
703                         0,
704                         sizeof (PciData),
705                         &PciData
706                         );
707   if (EFI_ERROR (Status)) {
708     gBS->CloseProtocol (
709           Controller,
710           &gEfiPciIoProtocolGuid,
711           This->DriverBindingHandle,
712           Controller
713           );
714     return EFI_UNSUPPORTED;
715   }
716 
717   //
718   // Since we already got the PciData, we can close protocol to avoid to carry it on for multiple exit points.
719   //
720   gBS->CloseProtocol (
721         Controller,
722         &gEfiPciIoProtocolGuid,
723         This->DriverBindingHandle,
724         Controller
725         );
726 
727   //
728   // Examine UFS Host Controller PCI Configuration table fields
729   //
730   if (PciData.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE) {
731     if (PciData.Hdr.ClassCode[1] == 0x09 ) { //UFS Controller Subclass
732       UfsHcFound = TRUE;
733     }
734   }
735 
736   if (!UfsHcFound) {
737     return EFI_UNSUPPORTED;
738   }
739 
740   return Status;
741 }
742 
743 /**
744   Starts a device controller or a bus controller.
745 
746   The Start() function is designed to be invoked from the EFI boot service ConnectController().
747   As a result, much of the error checking on the parameters to Start() has been moved into this
748   common boot service. It is legal to call Start() from other locations,
749   but the following calling restrictions must be followed or the system behavior will not be deterministic.
750   1. ControllerHandle must be a valid EFI_HANDLE.
751   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
752      EFI_DEVICE_PATH_PROTOCOL.
753   3. Prior to calling Start(), the Supported() function for the driver specified by This must
754      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
755 
756   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
757   @param[in]  ControllerHandle     The handle of the controller to start. This handle
758                                    must support a protocol interface that supplies
759                                    an I/O abstraction to the driver.
760   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
761                                    parameter is ignored by device drivers, and is optional for bus
762                                    drivers. For a bus driver, if this parameter is NULL, then handles
763                                    for all the children of Controller are created by this driver.
764                                    If this parameter is not NULL and the first Device Path Node is
765                                    not the End of Device Path Node, then only the handle for the
766                                    child device specified by the first Device Path Node of
767                                    RemainingDevicePath is created by this driver.
768                                    If the first Device Path Node of RemainingDevicePath is
769                                    the End of Device Path Node, no child handle is created by this
770                                    driver.
771 
772   @retval EFI_SUCCESS              The device was started.
773   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
774   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
775   @retval Others                   The driver failded to start the device.
776 
777 **/
778 EFI_STATUS
779 EFIAPI
UfsHcDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)780 UfsHcDriverBindingStart (
781   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
782   IN EFI_HANDLE                   Controller,
783   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
784   )
785 {
786   EFI_STATUS                        Status;
787   EFI_PCI_IO_PROTOCOL               *PciIo;
788   UFS_HOST_CONTROLLER_PRIVATE_DATA  *Private;
789   UINT64                            Supports;
790   UINT8                             BarIndex;
791   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
792   UINT32                            BaseAddress;
793 
794   PciIo    = NULL;
795   Private  = NULL;
796   Supports = 0;
797   BarDesc  = NULL;
798   BaseAddress = PcdGet32 (PcdDwUfsHcDxeBaseAddress);
799 
800   //
801   // Now test and open the EfiPciIoProtocol
802   //
803   Status = gBS->OpenProtocol (
804                   Controller,
805                   &gEfiPciIoProtocolGuid,
806                   (VOID **) &PciIo,
807                   This->DriverBindingHandle,
808                   Controller,
809                   EFI_OPEN_PROTOCOL_BY_DRIVER
810                   );
811   //
812   // Status == 0 - A normal execution flow, SUCCESS and the program proceeds.
813   // Status == ALREADY_STARTED - A non-zero Status code returned. It indicates
814   //           that the protocol has been opened and should be treated as a
815   //           normal condition and the program proceeds. The Protocol will not
816   //           opened 'again' by this call.
817   // Status != ALREADY_STARTED - Error status, terminate program execution
818   //
819   if (EFI_ERROR (Status)) {
820     //
821     // EFI_ALREADY_STARTED is also an error
822     //
823     return Status;
824   }
825 
826   //BaseAddress = PcdGet32 (PcdDwUfsHcDxeBaseAddress);
827   Private = AllocateCopyPool (sizeof (UFS_HOST_CONTROLLER_PRIVATE_DATA), &gUfsHcTemplate);
828   if (Private == NULL) {
829     Status = EFI_OUT_OF_RESOURCES;
830     goto Done;
831   }
832 
833   Private->RegBase = (UINTN)BaseAddress;
834   Private->PciIo = PciIo;
835 
836   for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
837     Status = PciIo->GetBarAttributes (
838                       PciIo,
839                       BarIndex,
840                       NULL,
841                       (VOID**) &BarDesc
842                       );
843     if (Status == EFI_UNSUPPORTED) {
844       continue;
845     } else if (EFI_ERROR (Status)) {
846       goto Done;
847     }
848 
849     if (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
850       Private->BarIndex = BarIndex;
851       FreePool (BarDesc);
852       break;
853     }
854 
855     FreePool (BarDesc);
856   }
857 
858   Status = PciIo->Attributes (
859                     PciIo,
860                     EfiPciIoAttributeOperationGet,
861                     0,
862                     &Private->PciAttributes
863                     );
864 
865   if (EFI_ERROR (Status)) {
866     goto Done;
867   }
868 
869   Status = PciIo->Attributes (
870                     PciIo,
871                     EfiPciIoAttributeOperationSupported,
872                     0,
873                     &Supports
874                     );
875 
876   if (!EFI_ERROR (Status)) {
877     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
878     Status    = PciIo->Attributes (
879                          PciIo,
880                          EfiPciIoAttributeOperationEnable,
881                          Supports,
882                          NULL
883                          );
884   } else {
885     goto Done;
886   }
887 
888   ///
889   /// Install UFS_HOST_CONTROLLER protocol
890   ///
891   Status = gBS->InstallProtocolInterface (
892                   &Controller,
893                   &gEdkiiUfsHostControllerProtocolGuid,
894                   EFI_NATIVE_INTERFACE,
895                   (VOID*)&(Private->UfsHc)
896                   );
897 
898 Done:
899   if (EFI_ERROR (Status)) {
900     if ((Private != NULL) && (Private->PciAttributes != 0)) {
901       //
902       // Restore original PCI attributes
903       //
904       Status = PciIo->Attributes (
905                         PciIo,
906                         EfiPciIoAttributeOperationSet,
907                         Private->PciAttributes,
908                         NULL
909                         );
910       ASSERT_EFI_ERROR (Status);
911     }
912     gBS->CloseProtocol (
913           Controller,
914           &gEfiPciIoProtocolGuid,
915           This->DriverBindingHandle,
916           Controller
917           );
918     if (Private != NULL) {
919       FreePool (Private);
920     }
921   }
922 
923   return Status;
924 }
925 
926 /**
927   Stops a device controller or a bus controller.
928 
929   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
930   As a result, much of the error checking on the parameters to Stop() has been moved
931   into this common boot service. It is legal to call Stop() from other locations,
932   but the following calling restrictions must be followed or the system behavior will not be deterministic.
933   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
934      same driver's Start() function.
935   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
936      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
937      Start() function, and the Start() function must have called OpenProtocol() on
938      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
939 
940   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
941   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
942                                 support a bus specific I/O protocol for the driver
943                                 to use to stop the device.
944   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
945   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
946                                 if NumberOfChildren is 0.
947 
948   @retval EFI_SUCCESS           The device was stopped.
949   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
950 
951 **/
952 EFI_STATUS
953 EFIAPI
UfsHcDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)954 UfsHcDriverBindingStop (
955   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
956   IN  EFI_HANDLE                      Controller,
957   IN  UINTN                           NumberOfChildren,
958   IN  EFI_HANDLE                      *ChildHandleBuffer
959   )
960 {
961   EFI_STATUS                          Status;
962   UFS_HOST_CONTROLLER_PRIVATE_DATA    *Private;
963   EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHc;
964 
965   ///
966   /// Get private data
967   ///
968   Status = gBS->OpenProtocol (
969                   Controller,
970                   &gEdkiiUfsHostControllerProtocolGuid,
971                   (VOID **) &UfsHc,
972                   This->DriverBindingHandle,
973                   Controller,
974                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
975                   );
976 
977   if (EFI_ERROR (Status)) {
978     return EFI_DEVICE_ERROR;
979   }
980 
981   Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (UfsHc);
982 
983   Status = gBS->UninstallProtocolInterface (
984                   Controller,
985                   &gEdkiiUfsHostControllerProtocolGuid,
986                   &(Private->UfsHc)
987                   );
988   if (!EFI_ERROR (Status)) {
989     //
990     // Restore original PCI attributes
991     //
992     Status = Private->PciIo->Attributes (
993                                Private->PciIo,
994                                EfiPciIoAttributeOperationSet,
995                                Private->PciAttributes,
996                                NULL
997                                );
998     ASSERT_EFI_ERROR (Status);
999 
1000     //
1001     // Close protocols opened by UFS host controller driver
1002     //
1003     gBS->CloseProtocol (
1004            Controller,
1005            &gEfiPciIoProtocolGuid,
1006            This->DriverBindingHandle,
1007            Controller
1008            );
1009 
1010     FreePool (Private);
1011   }
1012 
1013   return Status;
1014 }
1015 
1016 /**
1017   The entry point for UFS host controller driver, used to install this driver on the ImageHandle.
1018 
1019   @param[in]  ImageHandle   The firmware allocated handle for this driver image.
1020   @param[in]  SystemTable   Pointer to the EFI system table.
1021 
1022   @retval EFI_SUCCESS   Driver loaded.
1023   @retval other         Driver not loaded.
1024 
1025 **/
1026 EFI_STATUS
1027 EFIAPI
UfsHcDriverEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1028 UfsHcDriverEntry (
1029   IN EFI_HANDLE        ImageHandle,
1030   IN EFI_SYSTEM_TABLE  *SystemTable
1031   )
1032 {
1033   EFI_STATUS           Status;
1034 
1035   Status = EfiLibInstallDriverBindingComponentName2 (
1036              ImageHandle,
1037              SystemTable,
1038              &gUfsHcDriverBinding,
1039              ImageHandle,
1040              &gUfsHcComponentName,
1041              &gUfsHcComponentName2
1042              );
1043   ASSERT_EFI_ERROR (Status);
1044 
1045   return Status;
1046 }
1047