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 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 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 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 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 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 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 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 309 UfsHcFlush ( 310 IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This 311 ) 312 { 313 return EFI_SUCCESS; 314 } 315 316 /** 317 Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space. 318 319 @param This A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance. 320 @param Width Signifies the width of the memory operations. 321 @param Offset The offset within the UFS Host Controller MMIO space to start the 322 memory operation. 323 @param Count The number of memory operations to perform. 324 @param Buffer For read operations, the destination buffer to store the results. 325 For write operations, the source buffer to write data from. 326 327 @retval EFI_SUCCESS The data was read from or written to the UFS host controller. 328 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not 329 valid for the UFS Host Controller memory space. 330 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 331 @retval EFI_INVALID_PARAMETER One or more parameters are invalid. 332 333 **/ 334 EFI_STATUS 335 EFIAPI 336 UfsHcMmioRead ( 337 IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This, 338 IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH Width, 339 IN UINT64 Offset, 340 IN UINTN Count, 341 IN OUT VOID *Buffer 342 ) 343 { 344 UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; 345 UINTN Index; 346 347 Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); 348 349 switch (Width) { 350 case EfiUfsHcWidthUint8: 351 for (Index = 0; Index < Count; Index++) { 352 *((UINT8 *)Buffer + Index) = MmioRead8 (Private->RegBase + Offset); 353 } 354 break; 355 case EfiUfsHcWidthUint16: 356 for (Index = 0; Index < Count; Index++) { 357 *((UINT16 *)Buffer + Index) = MmioRead16 (Private->RegBase + Offset); 358 } 359 break; 360 case EfiUfsHcWidthUint32: 361 for (Index = 0; Index < Count; Index++) { 362 *((UINT32 *)Buffer + Index) = MmioRead32 (Private->RegBase + Offset); 363 } 364 break; 365 case EfiUfsHcWidthUint64: 366 for (Index = 0; Index < Count; Index++) { 367 *((UINT64 *)Buffer + Index) = MmioRead64 (Private->RegBase + Offset); 368 } 369 break; 370 default: 371 return EFI_INVALID_PARAMETER; 372 } 373 374 return EFI_SUCCESS; 375 } 376 377 /** 378 Enable a UFS bus driver to access UFS MMIO registers in the UFS Host Controller memory space. 379 380 @param This A pointer to the EDKII_UFS_HOST_CONTROLLER_PROTOCOL instance. 381 @param Width Signifies the width of the memory operations. 382 @param Offset The offset within the UFS Host Controller MMIO space to start the 383 memory operation. 384 @param Count The number of memory operations to perform. 385 @param Buffer For read operations, the destination buffer to store the results. 386 For write operations, the source buffer to write data from. 387 388 @retval EFI_SUCCESS The data was read from or written to the UFS host controller. 389 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not 390 valid for the UFS Host Controller memory space. 391 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 392 @retval EFI_INVALID_PARAMETER One or more parameters are invalid. 393 394 **/ 395 EFI_STATUS 396 EFIAPI 397 UfsHcMmioWrite ( 398 IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This, 399 IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL_WIDTH Width, 400 IN UINT64 Offset, 401 IN UINTN Count, 402 IN OUT VOID *Buffer 403 ) 404 { 405 UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; 406 EFI_STATUS Status = EFI_SUCCESS; 407 UINTN Index; 408 409 Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); 410 411 switch (Width) { 412 case EfiUfsHcWidthUint8: 413 for (Index = 0; Index < Count; Index++) { 414 Status = MmioWrite8 (Private->RegBase + Offset, *((UINT8 *)Buffer + Index)); 415 } 416 break; 417 case EfiUfsHcWidthUint16: 418 for (Index = 0; Index < Count; Index++) { 419 Status = MmioWrite16 (Private->RegBase + Offset, *((UINT16 *)Buffer + Index)); 420 } 421 break; 422 case EfiUfsHcWidthUint32: 423 for (Index = 0; Index < Count; Index++) { 424 Status = MmioWrite32 (Private->RegBase + Offset, *((UINT32 *)Buffer + Index)); 425 } 426 break; 427 case EfiUfsHcWidthUint64: 428 for (Index = 0; Index < Count; Index++) { 429 Status = MmioWrite64 (Private->RegBase + Offset, *((UINT64 *)Buffer + Index)); 430 } 431 break; 432 default: 433 return EFI_INVALID_PARAMETER; 434 } 435 436 return Status; 437 } 438 439 EFI_STATUS 440 EFIAPI 441 UfsHcPhyInit ( 442 IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This 443 ) 444 { 445 UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; 446 EFI_STATUS Status; 447 UINT32 Data, Fsm0, Fsm1; 448 449 Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); 450 DwUfsDmeSet (Private->RegBase, 0xd0c1, 0, 1); 451 DwUfsDmeSet (Private->RegBase, 0xd0c1, 0, 1); 452 DwUfsDmeSet (Private->RegBase, 0x156a, 0, 2); 453 DwUfsDmeSet (Private->RegBase, 0x8114, 0, 1); 454 DwUfsDmeSet (Private->RegBase, 0x8121, 0, 0x2d); 455 DwUfsDmeSet (Private->RegBase, 0x8122, 0, 1); 456 DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1); 457 DwUfsDmeSet (Private->RegBase, 0x800d, 4, 0x58); 458 DwUfsDmeSet (Private->RegBase, 0x800d, 5, 0x58); 459 DwUfsDmeSet (Private->RegBase, 0x800e, 4, 0xb); 460 DwUfsDmeSet (Private->RegBase, 0x800e, 5, 0xb); 461 DwUfsDmeSet (Private->RegBase, 0x8009, 4, 0x1); 462 DwUfsDmeSet (Private->RegBase, 0x8009, 5, 0x1); 463 DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1); 464 DwUfsDmeSet (Private->RegBase, 0x8113, 0, 1); 465 DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1); 466 DwUfsDmeSet (Private->RegBase, 0x0095, 4, 0x4a); 467 DwUfsDmeSet (Private->RegBase, 0x0095, 5, 0x4a); 468 DwUfsDmeSet (Private->RegBase, 0x0094, 4, 0x4a); 469 DwUfsDmeSet (Private->RegBase, 0x0094, 5, 0x4a); 470 DwUfsDmeSet (Private->RegBase, 0x008f, 4, 0x7); 471 DwUfsDmeSet (Private->RegBase, 0x008f, 5, 0x7); 472 DwUfsDmeSet (Private->RegBase, 0x000f, 0, 0x5); 473 DwUfsDmeSet (Private->RegBase, 0x000f, 1, 0x5); 474 DwUfsDmeSet (Private->RegBase, 0xd085, 0, 1); 475 476 Status = DwUfsDmeGet (Private->RegBase, 0xd0c1, 0, &Data); 477 ASSERT_EFI_ERROR (Status); 478 ASSERT (Data == 1); 479 480 DwUfsDmeSet (Private->RegBase, 0xd0c1, 0, 0); 481 for (;;) { 482 Status = DwUfsDmeGet (Private->RegBase, 0x0041, 0, &Fsm0); 483 ASSERT_EFI_ERROR (Status); 484 Status = DwUfsDmeGet (Private->RegBase, 0x0041, 1, &Fsm1); 485 ASSERT_EFI_ERROR (Status); 486 if ((Fsm0 == 1) && (Fsm1 == 1)) { 487 break; 488 } 489 } 490 491 MmioWrite32 (Private->RegBase + UFS_HC_HCLKDIV_OFFSET, 0xE4); 492 Data = MmioRead32 (Private->RegBase + UFS_HC_AHIT_OFFSET); 493 Data &= ~0x3FF; 494 MmioWrite32 (Private->RegBase + UFS_HC_AHIT_OFFSET, Data); 495 496 DwUfsDmeSet (Private->RegBase, 0x155e, 0, 0); 497 DwUfsDmeSet (Private->RegBase, 0xd0ab, 0, 0); 498 499 Status = DwUfsDmeGet (Private->RegBase, 0xd0ab, 0, &Data); 500 ASSERT_EFI_ERROR ((Status) && (Data == 0)); 501 502 DwUfsDmeSet (Private->RegBase, 0x2044, 0, 0); 503 DwUfsDmeSet (Private->RegBase, 0x2045, 0, 0); 504 DwUfsDmeSet (Private->RegBase, 0x2040, 0, 9); 505 return EFI_SUCCESS; 506 } 507 508 EFI_STATUS 509 EFIAPI 510 UfsHcPhySetPowerMode ( 511 IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This 512 ) 513 { 514 UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; 515 UINT32 Data, TxLanes, RxLanes; 516 517 Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); 518 // PA_Tactive 519 DwUfsDmeGet (Private->RegBase, 0x15A8, 0, &Data); 520 if (Data < 7) { 521 DwUfsDmeSet (Private->RegBase, 0x15A8, 4, 7); 522 } 523 DwUfsDmeGet (Private->RegBase, 0x1561, 0, &TxLanes); 524 DwUfsDmeGet (Private->RegBase, 0x1581, 0, &RxLanes); 525 526 // PA TxSkip 527 DwUfsDmeSet (Private->RegBase, 0x155C, 0, 0); 528 // PA TxGear 529 DwUfsDmeSet (Private->RegBase, 0x1568, 0, 3); 530 // PA RxGear 531 DwUfsDmeSet (Private->RegBase, 0x1583, 0, 3); 532 // PA HSSeries 533 DwUfsDmeSet (Private->RegBase, 0x156A, 0, 2); 534 // PA TxTermination 535 DwUfsDmeSet (Private->RegBase, 0x1569, 0, 1); 536 // PA RxTermination 537 DwUfsDmeSet (Private->RegBase, 0x1584, 0, 1); 538 // PA Scrambling 539 DwUfsDmeSet (Private->RegBase, 0x1585, 0, 0); 540 // PA ActiveTxDataLines 541 DwUfsDmeSet (Private->RegBase, 0x1560, 0, TxLanes); 542 // PA ActiveRxDataLines 543 DwUfsDmeSet (Private->RegBase, 0x1580, 0, RxLanes); 544 // PA_PWRModeUserData0 = 8191 545 DwUfsDmeSet (Private->RegBase, 0x15B0, 0, 8191); 546 // PA_PWRModeUserData1 = 65535 547 DwUfsDmeSet (Private->RegBase, 0x15B1, 0, 65535); 548 // PA_PWRModeUserData2 = 32767 549 DwUfsDmeSet (Private->RegBase, 0x15B2, 0, 32767); 550 // DME_FC0ProtectionTimeOutVal = 8191 551 DwUfsDmeSet (Private->RegBase, 0xD041, 0, 8191); 552 // DME_TC0ReplayTimeOutVal = 65535 553 DwUfsDmeSet (Private->RegBase, 0xD042, 0, 65535); 554 // DME_AFC0ReqTimeOutVal = 32767 555 DwUfsDmeSet (Private->RegBase, 0xD043, 0, 32767); 556 // PA_PWRModeUserData3 = 8191 557 DwUfsDmeSet (Private->RegBase, 0x15B3, 0, 8191); 558 // PA_PWRModeUserData4 = 65535 559 DwUfsDmeSet (Private->RegBase, 0x15B4, 0, 65535); 560 // PA_PWRModeUserData5 = 32767 561 DwUfsDmeSet (Private->RegBase, 0x15B5, 0, 32767); 562 // DME_FC1ProtectionTimeOutVal = 8191 563 DwUfsDmeSet (Private->RegBase, 0xD044, 0, 8191); 564 // DME_TC1ReplayTimeOutVal = 65535 565 DwUfsDmeSet (Private->RegBase, 0xD045, 0, 65535); 566 // DME_AFC1ReqTimeOutVal = 32767 567 DwUfsDmeSet (Private->RegBase, 0xD046, 0, 32767); 568 569 DwUfsDmeSet (Private->RegBase, 0x1571, 0, 0x11); 570 do { 571 Data = MmioRead32(Private->RegBase + UFS_HC_IS_OFFSET); 572 } while ((Data & UFS_INT_UPMS) == 0); 573 MmioWrite32(Private->RegBase + UFS_HC_IS_OFFSET, UFS_INT_UPMS); 574 Data = MmioRead32(Private->RegBase + UFS_HC_STATUS_OFFSET); 575 if ((Data & HCS_UPMCRS_MASK) == HCS_PWR_LOCAL) { 576 DEBUG ((DEBUG_INFO, "ufs: change power mode success\n")); 577 } else { 578 DEBUG ((DEBUG_ERROR, "ufs: HCS.UPMCRS error, HCS:0x%x\n", Data)); 579 } 580 return EFI_SUCCESS; 581 } 582 583 /** 584 Tests to see if this driver supports a given controller. If a child device is provided, 585 it further tests to see if this driver supports creating a handle for the specified child device. 586 587 This function checks to see if the driver specified by This supports the device specified by 588 ControllerHandle. Drivers will typically use the device path attached to 589 ControllerHandle and/or the services from the bus I/O abstraction attached to 590 ControllerHandle to determine if the driver supports ControllerHandle. This function 591 may be called many times during platform initialization. In order to reduce boot times, the tests 592 performed by this function must be very small, and take as little time as possible to execute. This 593 function must not change the state of any hardware devices, and this function must be aware that the 594 device specified by ControllerHandle may already be managed by the same driver or a 595 different driver. This function must match its calls to AllocatePages() with FreePages(), 596 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). 597 Since ControllerHandle may have been previously started by the same driver, if a protocol is 598 already in the opened state, then it must not be closed with CloseProtocol(). This is required 599 to guarantee the state of ControllerHandle is not modified by this function. 600 601 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 602 @param[in] ControllerHandle The handle of the controller to test. This handle 603 must support a protocol interface that supplies 604 an I/O abstraction to the driver. 605 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This 606 parameter is ignored by device drivers, and is optional for bus 607 drivers. For bus drivers, if this parameter is not NULL, then 608 the bus driver must determine if the bus controller specified 609 by ControllerHandle and the child controller specified 610 by RemainingDevicePath are both supported by this 611 bus driver. 612 613 @retval EFI_SUCCESS The device specified by ControllerHandle and 614 RemainingDevicePath is supported by the driver specified by This. 615 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and 616 RemainingDevicePath is already being managed by the driver 617 specified by This. 618 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and 619 RemainingDevicePath is already being managed by a different 620 driver or an application that requires exclusive access. 621 Currently not implemented. 622 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and 623 RemainingDevicePath is not supported by the driver specified by This. 624 **/ 625 EFI_STATUS 626 EFIAPI 627 UfsHcDriverBindingSupported ( 628 IN EFI_DRIVER_BINDING_PROTOCOL *This, 629 IN EFI_HANDLE Controller, 630 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 631 ) 632 { 633 EFI_STATUS Status; 634 BOOLEAN UfsHcFound; 635 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath = NULL; 636 EFI_PCI_IO_PROTOCOL *PciIo = NULL; 637 PCI_TYPE00 PciData; 638 639 ParentDevicePath = NULL; 640 UfsHcFound = FALSE; 641 642 // 643 // UfsHcDxe is a device driver, and should ingore the 644 // "RemainingDevicePath" according to EFI spec 645 // 646 Status = gBS->OpenProtocol ( 647 Controller, 648 &gEfiDevicePathProtocolGuid, 649 (VOID *) &ParentDevicePath, 650 This->DriverBindingHandle, 651 Controller, 652 EFI_OPEN_PROTOCOL_BY_DRIVER 653 ); 654 if (EFI_ERROR (Status)) { 655 // 656 // EFI_ALREADY_STARTED is also an error 657 // 658 return Status; 659 } 660 // 661 // Close the protocol because we don't use it here 662 // 663 gBS->CloseProtocol ( 664 Controller, 665 &gEfiDevicePathProtocolGuid, 666 This->DriverBindingHandle, 667 Controller 668 ); 669 670 // 671 // Now test the EfiPciIoProtocol 672 // 673 Status = gBS->OpenProtocol ( 674 Controller, 675 &gEfiPciIoProtocolGuid, 676 (VOID **) &PciIo, 677 This->DriverBindingHandle, 678 Controller, 679 EFI_OPEN_PROTOCOL_BY_DRIVER 680 ); 681 if (EFI_ERROR (Status)) { 682 return Status; 683 } 684 // 685 // Now further check the PCI header: Base class (offset 0x0B) and 686 // Sub Class (offset 0x0A). This controller should be an UFS controller 687 // 688 Status = PciIo->Pci.Read ( 689 PciIo, 690 EfiPciIoWidthUint8, 691 0, 692 sizeof (PciData), 693 &PciData 694 ); 695 if (EFI_ERROR (Status)) { 696 gBS->CloseProtocol ( 697 Controller, 698 &gEfiPciIoProtocolGuid, 699 This->DriverBindingHandle, 700 Controller 701 ); 702 return EFI_UNSUPPORTED; 703 } 704 705 // 706 // Since we already got the PciData, we can close protocol to avoid to carry it on for multiple exit points. 707 // 708 gBS->CloseProtocol ( 709 Controller, 710 &gEfiPciIoProtocolGuid, 711 This->DriverBindingHandle, 712 Controller 713 ); 714 715 // 716 // Examine UFS Host Controller PCI Configuration table fields 717 // 718 if (PciData.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE) { 719 if (PciData.Hdr.ClassCode[1] == 0x09 ) { //UFS Controller Subclass 720 UfsHcFound = TRUE; 721 } 722 } 723 724 if (!UfsHcFound) { 725 return EFI_UNSUPPORTED; 726 } 727 728 return Status; 729 } 730 731 /** 732 Starts a device controller or a bus controller. 733 734 The Start() function is designed to be invoked from the EFI boot service ConnectController(). 735 As a result, much of the error checking on the parameters to Start() has been moved into this 736 common boot service. It is legal to call Start() from other locations, 737 but the following calling restrictions must be followed or the system behavior will not be deterministic. 738 1. ControllerHandle must be a valid EFI_HANDLE. 739 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned 740 EFI_DEVICE_PATH_PROTOCOL. 741 3. Prior to calling Start(), the Supported() function for the driver specified by This must 742 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. 743 744 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 745 @param[in] ControllerHandle The handle of the controller to start. This handle 746 must support a protocol interface that supplies 747 an I/O abstraction to the driver. 748 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This 749 parameter is ignored by device drivers, and is optional for bus 750 drivers. For a bus driver, if this parameter is NULL, then handles 751 for all the children of Controller are created by this driver. 752 If this parameter is not NULL and the first Device Path Node is 753 not the End of Device Path Node, then only the handle for the 754 child device specified by the first Device Path Node of 755 RemainingDevicePath is created by this driver. 756 If the first Device Path Node of RemainingDevicePath is 757 the End of Device Path Node, no child handle is created by this 758 driver. 759 760 @retval EFI_SUCCESS The device was started. 761 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. 762 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 763 @retval Others The driver failded to start the device. 764 765 **/ 766 EFI_STATUS 767 EFIAPI 768 UfsHcDriverBindingStart ( 769 IN EFI_DRIVER_BINDING_PROTOCOL *This, 770 IN EFI_HANDLE Controller, 771 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 772 ) 773 { 774 EFI_STATUS Status; 775 EFI_PCI_IO_PROTOCOL *PciIo; 776 UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; 777 UINT64 Supports; 778 UINT8 BarIndex; 779 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; 780 UINT32 BaseAddress; 781 782 PciIo = NULL; 783 Private = NULL; 784 Supports = 0; 785 BarDesc = NULL; 786 BaseAddress = PcdGet32 (PcdDwUfsHcDxeBaseAddress); 787 788 // 789 // Now test and open the EfiPciIoProtocol 790 // 791 Status = gBS->OpenProtocol ( 792 Controller, 793 &gEfiPciIoProtocolGuid, 794 (VOID **) &PciIo, 795 This->DriverBindingHandle, 796 Controller, 797 EFI_OPEN_PROTOCOL_BY_DRIVER 798 ); 799 // 800 // Status == 0 - A normal execution flow, SUCCESS and the program proceeds. 801 // Status == ALREADY_STARTED - A non-zero Status code returned. It indicates 802 // that the protocol has been opened and should be treated as a 803 // normal condition and the program proceeds. The Protocol will not 804 // opened 'again' by this call. 805 // Status != ALREADY_STARTED - Error status, terminate program execution 806 // 807 if (EFI_ERROR (Status)) { 808 // 809 // EFI_ALREADY_STARTED is also an error 810 // 811 return Status; 812 } 813 814 //BaseAddress = PcdGet32 (PcdDwUfsHcDxeBaseAddress); 815 Private = AllocateCopyPool (sizeof (UFS_HOST_CONTROLLER_PRIVATE_DATA), &gUfsHcTemplate); 816 if (Private == NULL) { 817 Status = EFI_OUT_OF_RESOURCES; 818 goto Done; 819 } 820 821 Private->RegBase = (UINTN)BaseAddress; 822 Private->PciIo = PciIo; 823 824 for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) { 825 Status = PciIo->GetBarAttributes ( 826 PciIo, 827 BarIndex, 828 NULL, 829 (VOID**) &BarDesc 830 ); 831 if (Status == EFI_UNSUPPORTED) { 832 continue; 833 } else if (EFI_ERROR (Status)) { 834 goto Done; 835 } 836 837 if (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) { 838 Private->BarIndex = BarIndex; 839 FreePool (BarDesc); 840 break; 841 } 842 843 FreePool (BarDesc); 844 } 845 846 Status = PciIo->Attributes ( 847 PciIo, 848 EfiPciIoAttributeOperationGet, 849 0, 850 &Private->PciAttributes 851 ); 852 853 if (EFI_ERROR (Status)) { 854 goto Done; 855 } 856 857 Status = PciIo->Attributes ( 858 PciIo, 859 EfiPciIoAttributeOperationSupported, 860 0, 861 &Supports 862 ); 863 864 if (!EFI_ERROR (Status)) { 865 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; 866 Status = PciIo->Attributes ( 867 PciIo, 868 EfiPciIoAttributeOperationEnable, 869 Supports, 870 NULL 871 ); 872 } else { 873 goto Done; 874 } 875 876 /// 877 /// Install UFS_HOST_CONTROLLER protocol 878 /// 879 Status = gBS->InstallProtocolInterface ( 880 &Controller, 881 &gEdkiiUfsHostControllerProtocolGuid, 882 EFI_NATIVE_INTERFACE, 883 (VOID*)&(Private->UfsHc) 884 ); 885 886 Done: 887 if (EFI_ERROR (Status)) { 888 if ((Private != NULL) && (Private->PciAttributes != 0)) { 889 // 890 // Restore original PCI attributes 891 // 892 Status = PciIo->Attributes ( 893 PciIo, 894 EfiPciIoAttributeOperationSet, 895 Private->PciAttributes, 896 NULL 897 ); 898 ASSERT_EFI_ERROR (Status); 899 } 900 gBS->CloseProtocol ( 901 Controller, 902 &gEfiPciIoProtocolGuid, 903 This->DriverBindingHandle, 904 Controller 905 ); 906 if (Private != NULL) { 907 FreePool (Private); 908 } 909 } 910 911 return Status; 912 } 913 914 /** 915 Stops a device controller or a bus controller. 916 917 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). 918 As a result, much of the error checking on the parameters to Stop() has been moved 919 into this common boot service. It is legal to call Stop() from other locations, 920 but the following calling restrictions must be followed or the system behavior will not be deterministic. 921 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this 922 same driver's Start() function. 923 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid 924 EFI_HANDLE. In addition, all of these handles must have been created in this driver's 925 Start() function, and the Start() function must have called OpenProtocol() on 926 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. 927 928 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 929 @param[in] ControllerHandle A handle to the device being stopped. The handle must 930 support a bus specific I/O protocol for the driver 931 to use to stop the device. 932 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. 933 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL 934 if NumberOfChildren is 0. 935 936 @retval EFI_SUCCESS The device was stopped. 937 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 938 939 **/ 940 EFI_STATUS 941 EFIAPI 942 UfsHcDriverBindingStop ( 943 IN EFI_DRIVER_BINDING_PROTOCOL *This, 944 IN EFI_HANDLE Controller, 945 IN UINTN NumberOfChildren, 946 IN EFI_HANDLE *ChildHandleBuffer 947 ) 948 { 949 EFI_STATUS Status; 950 UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; 951 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc; 952 953 /// 954 /// Get private data 955 /// 956 Status = gBS->OpenProtocol ( 957 Controller, 958 &gEdkiiUfsHostControllerProtocolGuid, 959 (VOID **) &UfsHc, 960 This->DriverBindingHandle, 961 Controller, 962 EFI_OPEN_PROTOCOL_GET_PROTOCOL 963 ); 964 965 if (EFI_ERROR (Status)) { 966 return EFI_DEVICE_ERROR; 967 } 968 969 Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (UfsHc); 970 971 Status = gBS->UninstallProtocolInterface ( 972 Controller, 973 &gEdkiiUfsHostControllerProtocolGuid, 974 &(Private->UfsHc) 975 ); 976 if (!EFI_ERROR (Status)) { 977 // 978 // Restore original PCI attributes 979 // 980 Status = Private->PciIo->Attributes ( 981 Private->PciIo, 982 EfiPciIoAttributeOperationSet, 983 Private->PciAttributes, 984 NULL 985 ); 986 ASSERT_EFI_ERROR (Status); 987 988 // 989 // Close protocols opened by UFS host controller driver 990 // 991 gBS->CloseProtocol ( 992 Controller, 993 &gEfiPciIoProtocolGuid, 994 This->DriverBindingHandle, 995 Controller 996 ); 997 998 FreePool (Private); 999 } 1000 1001 return Status; 1002 } 1003 1004 /** 1005 The entry point for UFS host controller driver, used to install this driver on the ImageHandle. 1006 1007 @param[in] ImageHandle The firmware allocated handle for this driver image. 1008 @param[in] SystemTable Pointer to the EFI system table. 1009 1010 @retval EFI_SUCCESS Driver loaded. 1011 @retval other Driver not loaded. 1012 1013 **/ 1014 EFI_STATUS 1015 EFIAPI 1016 UfsHcDriverEntry ( 1017 IN EFI_HANDLE ImageHandle, 1018 IN EFI_SYSTEM_TABLE *SystemTable 1019 ) 1020 { 1021 EFI_STATUS Status; 1022 1023 Status = EfiLibInstallDriverBindingComponentName2 ( 1024 ImageHandle, 1025 SystemTable, 1026 &gUfsHcDriverBinding, 1027 ImageHandle, 1028 &gUfsHcComponentName, 1029 &gUfsHcComponentName2 1030 ); 1031 ASSERT_EFI_ERROR (Status); 1032 1033 return Status; 1034 } 1035