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