1 /** @file 2 This file provides some helper functions which are specific for SD card device. 3 4 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "DwMmcHcDxe.h" 16 17 /** 18 Send command GO_IDLE_STATE to the device to make it go to Idle State. 19 20 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 21 22 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 23 @param[in] Slot The slot number of the SD card to send the command to. 24 25 @retval EFI_SUCCESS The SD device is reset correctly. 26 @retval Others The device reset fails. 27 28 **/ 29 EFI_STATUS 30 SdCardReset ( 31 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 32 IN UINT8 Slot 33 ) 34 { 35 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 36 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 37 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 38 EFI_STATUS Status; 39 40 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 41 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 42 ZeroMem (&Packet, sizeof (Packet)); 43 44 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 45 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 46 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 47 48 SdMmcCmdBlk.CommandIndex = SD_GO_IDLE_STATE; 49 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBc; 50 51 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 52 53 return Status; 54 } 55 56 /** 57 Send command SEND_IF_COND to the device to inquiry the SD Memory Card interface 58 condition. 59 60 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 61 62 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 63 @param[in] Slot The slot number of the SD card to send the command to. 64 @param[in] SupplyVoltage The supplied voltage by the host. 65 @param[in] CheckPattern The check pattern to be sent to the device. 66 67 @retval EFI_SUCCESS The operation is done correctly. 68 @retval Others The operation fails. 69 70 **/ 71 EFI_STATUS 72 SdCardVoltageCheck ( 73 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 74 IN UINT8 Slot, 75 IN UINT8 SupplyVoltage, 76 IN UINT8 CheckPattern 77 ) 78 { 79 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 80 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 81 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 82 EFI_STATUS Status; 83 84 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 85 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 86 ZeroMem (&Packet, sizeof (Packet)); 87 88 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 89 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 90 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 91 92 SdMmcCmdBlk.CommandIndex = SD_SEND_IF_COND; 93 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr; 94 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR7; 95 SdMmcCmdBlk.CommandArgument = (SupplyVoltage << 8) | CheckPattern; 96 97 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 98 99 if (!EFI_ERROR (Status)) { 100 if (SdMmcStatusBlk.Resp0 != SdMmcCmdBlk.CommandArgument) { 101 return EFI_DEVICE_ERROR; 102 } 103 } 104 105 return Status; 106 } 107 108 /** 109 Send command SDIO_SEND_OP_COND to the device to see whether it is SDIO device. 110 111 Refer to SDIO Simplified Spec 3 Section 3.2 for details. 112 113 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 114 @param[in] Slot The slot number of the SD card to send the command to. 115 @param[in] VoltageWindow The supply voltage window. 116 @param[in] S18R The boolean to show if it should switch to 1.8v. 117 118 @retval EFI_SUCCESS The operation is done correctly. 119 @retval Others The operation fails. 120 121 **/ 122 EFI_STATUS 123 SdioSendOpCond ( 124 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 125 IN UINT8 Slot, 126 IN UINT32 VoltageWindow, 127 IN BOOLEAN S18R 128 ) 129 { 130 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 131 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 132 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 133 EFI_STATUS Status; 134 UINT32 Switch; 135 136 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 137 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 138 ZeroMem (&Packet, sizeof (Packet)); 139 140 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 141 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 142 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 143 144 SdMmcCmdBlk.CommandIndex = SDIO_SEND_OP_COND; 145 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr; 146 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR4; 147 148 Switch = S18R ? BIT24 : 0; 149 150 SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch; 151 152 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 153 154 return Status; 155 } 156 157 /** 158 Send command SD_SEND_OP_COND to the device to see whether it is SDIO device. 159 160 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 161 162 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 163 @param[in] Slot The slot number of the SD card to send the command to. 164 @param[in] Rca The relative device address of addressed device. 165 @param[in] VoltageWindow The supply voltage window. 166 @param[in] S18R The boolean to show if it should switch to 1.8v. 167 @param[in] Xpc The boolean to show if it should provide 0.36w power control. 168 @param[in] Hcs The boolean to show if it support host capacity info. 169 @param[out] Ocr The buffer to store returned OCR register value. 170 171 @retval EFI_SUCCESS The operation is done correctly. 172 @retval Others The operation fails. 173 174 **/ 175 EFI_STATUS 176 SdCardSendOpCond ( 177 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 178 IN UINT8 Slot, 179 IN UINT16 Rca, 180 IN UINT32 VoltageWindow, 181 IN BOOLEAN S18R, 182 IN BOOLEAN Xpc, 183 IN BOOLEAN Hcs, 184 OUT UINT32 *Ocr 185 ) 186 { 187 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 188 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 189 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 190 EFI_STATUS Status; 191 UINT32 Switch; 192 UINT32 MaxPower; 193 UINT32 HostCapacity; 194 195 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 196 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 197 ZeroMem (&Packet, sizeof (Packet)); 198 199 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 200 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 201 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 202 203 SdMmcCmdBlk.CommandIndex = SD_APP_CMD; 204 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 205 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 206 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 207 208 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 209 if (EFI_ERROR (Status)) { 210 return Status; 211 } 212 213 SdMmcCmdBlk.CommandIndex = SD_SEND_OP_COND; 214 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr; 215 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR3; 216 217 Switch = S18R ? BIT24 : 0; 218 MaxPower = Xpc ? BIT28 : 0; 219 HostCapacity = Hcs ? BIT30 : 0; 220 221 SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch | MaxPower | HostCapacity; 222 223 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 224 if (!EFI_ERROR (Status)) { 225 // 226 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12. 227 // 228 *Ocr = SdMmcStatusBlk.Resp0; 229 } 230 231 return Status; 232 } 233 234 /** 235 Broadcast command ALL_SEND_CID to the bus to ask all the SD devices to send the 236 data of their CID registers. 237 238 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 239 240 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 241 @param[in] Slot The slot number of the SD card to send the command to. 242 243 @retval EFI_SUCCESS The operation is done correctly. 244 @retval Others The operation fails. 245 246 **/ 247 EFI_STATUS 248 SdCardAllSendCid ( 249 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 250 IN UINT8 Slot 251 ) 252 { 253 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 254 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 255 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 256 EFI_STATUS Status; 257 258 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 259 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 260 ZeroMem (&Packet, sizeof (Packet)); 261 262 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 263 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 264 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 265 266 SdMmcCmdBlk.CommandIndex = SD_ALL_SEND_CID; 267 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr; 268 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2; 269 270 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 271 272 return Status; 273 } 274 275 /** 276 Send command SET_RELATIVE_ADDR to the SD device to assign a Relative device 277 Address (RCA). 278 279 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 280 281 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 282 @param[in] Slot The slot number of the SD card to send the command to. 283 @param[out] Rca The relative device address to assign. 284 285 @retval EFI_SUCCESS The operation is done correctly. 286 @retval Others The operation fails. 287 288 **/ 289 EFI_STATUS 290 SdCardSetRca ( 291 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 292 IN UINT8 Slot, 293 OUT UINT16 *Rca 294 ) 295 { 296 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 297 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 298 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 299 EFI_STATUS Status; 300 301 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 302 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 303 ZeroMem (&Packet, sizeof (Packet)); 304 305 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 306 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 307 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 308 309 SdMmcCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR; 310 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr; 311 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR6; 312 313 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 314 if (!EFI_ERROR (Status)) { 315 *Rca = (UINT16)(SdMmcStatusBlk.Resp0 >> 16); 316 } 317 318 return Status; 319 } 320 321 /** 322 Send command SEND_CSD to the SD device to get the data of the CSD register. 323 324 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 325 326 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 327 @param[in] Slot The slot number of the SD card to send the command to. 328 @param[in] Rca The relative device address of selected device. 329 @param[out] Csd The buffer to store the content of the CSD register. 330 Note the caller should ignore the lowest byte of this 331 buffer as the content of this byte is meaningless even 332 if the operation succeeds. 333 334 @retval EFI_SUCCESS The operation is done correctly. 335 @retval Others The operation fails. 336 337 **/ 338 EFI_STATUS 339 SdCardGetCsd ( 340 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 341 IN UINT8 Slot, 342 IN UINT16 Rca, 343 OUT SD_CSD *Csd 344 ) 345 { 346 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 347 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 348 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 349 EFI_STATUS Status; 350 351 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 352 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 353 ZeroMem (&Packet, sizeof (Packet)); 354 355 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 356 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 357 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 358 359 SdMmcCmdBlk.CommandIndex = SD_SEND_CSD; 360 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 361 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2; 362 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 363 364 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 365 if (!EFI_ERROR (Status)) { 366 // 367 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12. 368 // 369 CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1); 370 } 371 372 return Status; 373 } 374 375 /** 376 Send command SEND_CSD to the SD device to get the data of the CSD register. 377 378 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 379 380 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 381 @param[in] Slot The slot number of the SD card to send the command to. 382 @param[in] Rca The relative device address of selected device. 383 @param[out] Scr The buffer to store the content of the SCR register. 384 385 @retval EFI_SUCCESS The operation is done correctly. 386 @retval Others The operation fails. 387 388 **/ 389 EFI_STATUS 390 SdCardGetScr ( 391 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 392 IN UINT8 Slot, 393 IN UINT16 Rca, 394 OUT SD_SCR *Scr 395 ) 396 { 397 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 398 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 399 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 400 EFI_STATUS Status; 401 402 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 403 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 404 ZeroMem (&Packet, sizeof (Packet)); 405 406 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 407 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 408 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 409 410 SdMmcCmdBlk.CommandIndex = SD_APP_CMD; 411 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 412 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 413 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 414 415 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 416 if (EFI_ERROR (Status)) { 417 return Status; 418 } 419 420 SdMmcCmdBlk.CommandIndex = SD_SEND_SCR; 421 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc; 422 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 423 424 Packet.InDataBuffer = Scr; 425 Packet.InTransferLength = sizeof (SD_SCR); 426 427 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 428 429 return Status; 430 } 431 432 /** 433 Send command SELECT_DESELECT_CARD to the SD device to select/deselect it. 434 435 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 436 437 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 438 @param[in] Slot The slot number of the SD card to send the command to. 439 @param[in] Rca The relative device address of selected device. 440 441 @retval EFI_SUCCESS The operation is done correctly. 442 @retval Others The operation fails. 443 444 **/ 445 EFI_STATUS 446 SdCardSelect ( 447 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 448 IN UINT8 Slot, 449 IN UINT16 Rca 450 ) 451 { 452 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 453 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 454 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 455 EFI_STATUS Status; 456 457 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 458 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 459 ZeroMem (&Packet, sizeof (Packet)); 460 461 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 462 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 463 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 464 465 SdMmcCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD; 466 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 467 if (Rca != 0) { 468 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b; 469 } 470 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 471 472 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 473 474 return Status; 475 } 476 477 /** 478 Send command VOLTAGE_SWITCH to the SD device to switch the voltage of the device. 479 480 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 481 482 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 483 @param[in] Slot The slot number of the SD card to send the command to. 484 485 @retval EFI_SUCCESS The operation is done correctly. 486 @retval Others The operation fails. 487 488 **/ 489 EFI_STATUS 490 SdCardVoltageSwitch ( 491 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 492 IN UINT8 Slot 493 ) 494 { 495 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 496 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 497 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 498 EFI_STATUS Status; 499 500 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 501 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 502 ZeroMem (&Packet, sizeof (Packet)); 503 504 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 505 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 506 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 507 508 SdMmcCmdBlk.CommandIndex = SD_VOLTAGE_SWITCH; 509 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 510 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 511 SdMmcCmdBlk.CommandArgument = 0; 512 513 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 514 515 return Status; 516 } 517 518 /** 519 Send command SET_BUS_WIDTH to the SD device to set the bus width. 520 521 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 522 523 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 524 @param[in] Slot The slot number of the SD card to send the command to. 525 @param[in] Rca The relative device address of addressed device. 526 @param[in] BusWidth The bus width to be set, it could be 1 or 4. 527 528 @retval EFI_SUCCESS The operation is done correctly. 529 @retval Others The operation fails. 530 531 **/ 532 EFI_STATUS 533 SdCardSetBusWidth ( 534 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 535 IN UINT8 Slot, 536 IN UINT16 Rca, 537 IN UINT8 BusWidth 538 ) 539 { 540 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 541 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 542 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 543 EFI_STATUS Status; 544 UINT8 Value; 545 546 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 547 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 548 ZeroMem (&Packet, sizeof (Packet)); 549 550 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 551 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 552 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 553 554 SdMmcCmdBlk.CommandIndex = SD_APP_CMD; 555 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 556 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 557 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 558 559 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 560 if (EFI_ERROR (Status)) { 561 return Status; 562 } 563 564 SdMmcCmdBlk.CommandIndex = SD_SET_BUS_WIDTH; 565 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 566 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 567 568 if (BusWidth == 1) { 569 Value = 0; 570 } else if (BusWidth == 4) { 571 Value = 2; 572 } else { 573 return EFI_INVALID_PARAMETER; 574 } 575 576 SdMmcCmdBlk.CommandArgument = Value & 0x3; 577 578 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 579 return Status; 580 } 581 582 /** 583 Send command SWITCH_FUNC to the SD device to check switchable function or switch card function. 584 585 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 586 587 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 588 @param[in] Slot The slot number of the SD card to send the command to. 589 @param[in] AccessMode The value for access mode group. 590 @param[in] CommandSystem The value for command set group. 591 @param[in] DriveStrength The value for drive length group. 592 @param[in] PowerLimit The value for power limit group. 593 @param[in] Mode Switch or check function. 594 @param[out] SwitchResp The return switch function status. 595 596 @retval EFI_SUCCESS The operation is done correctly. 597 @retval Others The operation fails. 598 599 **/ 600 EFI_STATUS 601 SdCardSwitch ( 602 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 603 IN UINT8 Slot, 604 IN UINT8 AccessMode, 605 IN UINT8 CommandSystem, 606 IN UINT8 DriveStrength, 607 IN UINT8 PowerLimit, 608 IN BOOLEAN Mode, 609 OUT UINT8 *SwitchResp 610 ) 611 { 612 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 613 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 614 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 615 EFI_STATUS Status; 616 UINT32 ModeValue; 617 618 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 619 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 620 ZeroMem (&Packet, sizeof (Packet)); 621 622 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 623 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 624 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 625 626 SdMmcCmdBlk.CommandIndex = SD_SWITCH_FUNC; 627 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc; 628 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 629 630 ModeValue = Mode ? BIT31 : 0; 631 SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \ 632 ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \ 633 ModeValue; 634 635 Packet.InDataBuffer = SwitchResp; 636 Packet.InTransferLength = 64; 637 638 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 639 640 return Status; 641 } 642 643 /** 644 Send command SEND_STATUS to the addressed SD device to get its status register. 645 646 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 647 648 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 649 @param[in] Slot The slot number of the SD card to send the command to. 650 @param[in] Rca The relative device address of addressed device. 651 @param[out] DevStatus The returned device status. 652 653 @retval EFI_SUCCESS The operation is done correctly. 654 @retval Others The operation fails. 655 656 **/ 657 EFI_STATUS 658 SdCardSendStatus ( 659 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 660 IN UINT8 Slot, 661 IN UINT16 Rca, 662 OUT UINT32 *DevStatus 663 ) 664 { 665 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 666 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 667 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 668 EFI_STATUS Status; 669 670 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 671 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 672 ZeroMem (&Packet, sizeof (Packet)); 673 674 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 675 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 676 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 677 678 SdMmcCmdBlk.CommandIndex = SD_SEND_STATUS; 679 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 680 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 681 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 682 683 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 684 if (!EFI_ERROR (Status)) { 685 *DevStatus = SdMmcStatusBlk.Resp0; 686 } 687 688 return Status; 689 } 690 691 /** 692 Send command SEND_TUNING_BLOCK to the SD device for HS200 optimal sampling point 693 detection. 694 695 It may be sent up to 40 times until the host finishes the tuning procedure. 696 697 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details. 698 699 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 700 @param[in] Slot The slot number of the SD card to send the command to. 701 702 @retval EFI_SUCCESS The operation is done correctly. 703 @retval Others The operation fails. 704 705 **/ 706 EFI_STATUS 707 SdCardSendTuningBlk ( 708 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 709 IN UINT8 Slot 710 ) 711 { 712 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 713 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 714 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 715 EFI_STATUS Status; 716 UINT8 TuningBlock[64]; 717 718 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 719 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 720 ZeroMem (&Packet, sizeof (Packet)); 721 722 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 723 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 724 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT; 725 726 SdMmcCmdBlk.CommandIndex = SD_SEND_TUNING_BLOCK; 727 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc; 728 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 729 SdMmcCmdBlk.CommandArgument = 0; 730 731 Packet.InDataBuffer = TuningBlock; 732 Packet.InTransferLength = sizeof (TuningBlock); 733 734 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL); 735 736 return Status; 737 } 738 739 /** 740 Switch the bus width to specified width. 741 742 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and 743 SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details. 744 745 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance. 746 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 747 @param[in] Slot The slot number of the SD card to send the command to. 748 @param[in] Rca The relative device address to be assigned. 749 @param[in] BusWidth The bus width to be set, it could be 4 or 8. 750 751 @retval EFI_SUCCESS The operation is done correctly. 752 @retval Others The operation fails. 753 754 **/ 755 EFI_STATUS 756 SdCardSwitchBusWidth ( 757 IN EFI_PCI_IO_PROTOCOL *PciIo, 758 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 759 IN UINT8 Slot, 760 IN UINT16 Rca, 761 IN BOOLEAN IsDdr, 762 IN UINT8 BusWidth 763 ) 764 { 765 EFI_STATUS Status; 766 UINT32 DevStatus; 767 768 Status = SdCardSetBusWidth (PassThru, Slot, Rca, BusWidth); 769 if (EFI_ERROR (Status)) { 770 DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth, Status)); 771 return Status; 772 } 773 774 Status = SdCardSendStatus (PassThru, Slot, Rca, &DevStatus); 775 if (EFI_ERROR (Status)) { 776 DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Send status fails with %r\n", Status)); 777 return Status; 778 } 779 // 780 // Check the switch operation is really successful or not. 781 // 782 if ((DevStatus >> 16) != 0) { 783 DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: The switch operation fails as DevStatus is 0x%08x\n", DevStatus)); 784 return EFI_DEVICE_ERROR; 785 } 786 787 Status = DwMmcHcSetBusWidth (PciIo, Slot, IsDdr, BusWidth); 788 789 return Status; 790 } 791 792 /** 793 Switch the high speed timing according to request. 794 795 Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and 796 SD Host Controller Simplified Spec 3.0 section Figure 2-29 for details. 797 798 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance. 799 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance. 800 @param[in] Slot The slot number of the SD card to send the command to. 801 @param[in] Rca The relative device address to be assigned. 802 @param[in] S18A The boolean to show if it's a UHS-I SD card. 803 @param[in] BusWidths The bus width of the SD card. 804 805 @retval EFI_SUCCESS The operation is done correctly. 806 @retval Others The operation fails. 807 808 **/ 809 EFI_STATUS 810 SdCardSetBusMode ( 811 IN EFI_PCI_IO_PROTOCOL *PciIo, 812 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru, 813 IN UINT8 Slot, 814 IN UINT16 Rca, 815 IN BOOLEAN S18A, 816 IN UINT32 BusWidths 817 ) 818 { 819 EFI_STATUS Status; 820 DW_MMC_HC_SLOT_CAP *Capability; 821 UINT32 ClockFreq; 822 UINT8 AccessMode; 823 UINT8 SwitchResp[64]; 824 DW_MMC_HC_PRIVATE_DATA *Private; 825 BOOLEAN IsDdr; 826 827 Private = DW_MMC_HC_PRIVATE_FROM_THIS (PassThru); 828 829 Capability = &Private->Capability[Slot]; 830 831 if ((Capability->BusWidth == 1) || (Capability->BusWidth == 4)) { 832 BusWidths &= Capability[Slot].BusWidth; 833 } else { 834 DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: BusWidths (%d) in capability are wrong\n", Capability->BusWidth)); 835 return EFI_INVALID_PARAMETER; 836 } 837 838 if (BusWidths == 0) { 839 DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Get wrong BusWidths:%d\n", BusWidths)); 840 return EFI_INVALID_PARAMETER; 841 } 842 843 if (Private->Capability[Slot].Ddr50) { 844 IsDdr = TRUE; 845 } else { 846 IsDdr = FALSE; 847 } 848 849 Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidths); 850 if (EFI_ERROR (Status)) { 851 DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Executing SdCardSwitchBusWidth fails with %r\n", Status)); 852 return Status; 853 } 854 855 // 856 // Get the supported bus speed from SWITCH cmd return data group #1. 857 // 858 Status = SdCardSwitch (PassThru, Slot, 0xF, 0xF, 0xF, 0xF, FALSE, SwitchResp); 859 if (EFI_ERROR (Status)) { 860 return Status; 861 } 862 // 863 // Calculate supported bus speed/bus width/clock frequency by host and device capability. 864 // 865 ClockFreq = 0; 866 if (S18A && (Capability->Sdr104 != 0) && ((SwitchResp[13] & BIT3) != 0)) { 867 ClockFreq = 208; 868 AccessMode = 3; 869 } else if (S18A && (Capability->Sdr50 != 0) && ((SwitchResp[13] & BIT2) != 0)) { 870 ClockFreq = 100; 871 AccessMode = 2; 872 } else if (S18A && (Capability->Ddr50 != 0) && ((SwitchResp[13] & BIT4) != 0)) { 873 ClockFreq = 50; 874 AccessMode = 4; 875 } else if ((SwitchResp[13] & BIT1) != 0) { 876 ClockFreq = 50; 877 AccessMode = 1; 878 } else { 879 ClockFreq = 25; 880 AccessMode = 0; 881 } 882 883 Status = SdCardSwitch (PassThru, Slot, AccessMode, 0xF, 0xF, 0xF, TRUE, SwitchResp); 884 if (EFI_ERROR (Status)) { 885 return Status; 886 } 887 888 if ((SwitchResp[16] & 0xF) != AccessMode) { 889 DEBUG ((DEBUG_ERROR, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d fails! The Switch response is 0x%1x\n", AccessMode, ClockFreq, SwitchResp[16] & 0xF)); 890 return EFI_DEVICE_ERROR; 891 } 892 893 DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Switch to AccessMode %d ClockFreq %d \n", AccessMode, ClockFreq)); 894 895 Status = DwMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, *Capability); 896 if (EFI_ERROR (Status)) { 897 return Status; 898 } 899 900 return Status; 901 } 902 903 /** 904 Execute SD device identification procedure. 905 906 Refer to SD Physical Layer Simplified Spec 4.1 Section 3.6 for details. 907 908 @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA instance. 909 @param[in] Slot The slot number of the SD card to send the command to. 910 911 @retval EFI_SUCCESS There is a SD card. 912 @retval Others There is not a SD card. 913 914 **/ 915 EFI_STATUS 916 SdCardIdentification ( 917 IN DW_MMC_HC_PRIVATE_DATA *Private, 918 IN UINT8 Slot 919 ) 920 { 921 EFI_STATUS Status; 922 EFI_PCI_IO_PROTOCOL *PciIo; 923 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 924 UINT32 Ocr; 925 UINT16 Rca; 926 BOOLEAN Xpc; 927 BOOLEAN S18r; 928 UINT64 MaxCurrent; 929 SD_SCR Scr; 930 SD_CSD Csd; 931 932 PciIo = Private->PciIo; 933 PassThru = &Private->PassThru; 934 // 935 // 1. Send Cmd0 to the device 936 // 937 Status = SdCardReset (PassThru, Slot); 938 if (EFI_ERROR (Status)) { 939 DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd0 fails with %r\n", Status)); 940 return Status; 941 } 942 MicroSecondDelay (10000); 943 // 944 // 2. Send Cmd8 to the device 945 // 946 Status = SdCardVoltageCheck (PassThru, Slot, 0x1, 0xFF); 947 if (EFI_ERROR (Status)) { 948 DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd8 fails with %r\n", Status)); 949 return Status; 950 } 951 // 952 // 3. Send Acmd41 with voltage window 0 to the device 953 // 954 Status = SdCardSendOpCond (PassThru, Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr); 955 if (EFI_ERROR (Status)) { 956 DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing SdCardSendOpCond fails with %r\n", Status)); 957 return EFI_DEVICE_ERROR; 958 } 959 960 if (Private->Capability[Slot].Voltage33 != 0) { 961 // 962 // Support 3.3V 963 // 964 MaxCurrent = ((UINT32)Private->MaxCurrent[Slot] & 0xFF) * 4; 965 S18r = FALSE; 966 } else if (Private->Capability[Slot].Voltage30 != 0) { 967 // 968 // Support 3.0V 969 // 970 MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 8) & 0xFF) * 4; 971 S18r = FALSE; 972 } else if (Private->Capability[Slot].Voltage18 != 0) { 973 // 974 // Support 1.8V 975 // 976 MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 16) & 0xFF) * 4; 977 S18r = TRUE; 978 } else { 979 ASSERT (FALSE); 980 return EFI_DEVICE_ERROR; 981 } 982 983 if (MaxCurrent >= 150) { 984 Xpc = TRUE; 985 } else { 986 Xpc = FALSE; 987 } 988 989 // 990 // 4. Repeatly send Acmd41 with supply voltage window to the device. 991 // Note here we only support the cards complied with SD physical 992 // layer simplified spec version 2.0 and version 3.0 and above. 993 // 994 do { 995 Status = SdCardSendOpCond (PassThru, Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr); 996 if (EFI_ERROR (Status)) { 997 DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc)); 998 return EFI_DEVICE_ERROR; 999 } 1000 } while ((Ocr & BIT31) == 0); 1001 1002 Status = SdCardAllSendCid (PassThru, Slot); 1003 if (EFI_ERROR (Status)) { 1004 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardAllSendCid fails with %r\n", Status)); 1005 return Status; 1006 } 1007 1008 Status = SdCardSetRca (PassThru, Slot, &Rca); 1009 if (EFI_ERROR (Status)) { 1010 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardSetRca fails with %r\n", Status)); 1011 return Status; 1012 } 1013 1014 Status = SdCardGetCsd (PassThru, Slot, Rca, &Csd); 1015 if (EFI_ERROR (Status)) { 1016 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardGetCsd fails with %r\n", Status)); 1017 return Status; 1018 } 1019 1020 Status = SdCardSelect (PassThru, Slot, Rca); 1021 if (EFI_ERROR (Status)) { 1022 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Selecting card fails with %r\n", Status)); 1023 return Status; 1024 } 1025 1026 Status = SdCardGetScr (PassThru, Slot, Rca, &Scr); 1027 if (EFI_ERROR (Status)) { 1028 DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardGetScr fails with %r\n", Status)); 1029 return Status; 1030 } 1031 1032 // 1033 // Enter Data Tranfer Mode. 1034 // 1035 DEBUG ((DEBUG_INFO, "SdCardIdentification: Found a SD device at slot [%d]\n", Slot)); 1036 Private->Slot[Slot].CardType = SdCardType; 1037 1038 Status = SdCardSetBusMode (PciIo, PassThru, Slot, Rca, S18r, Scr.SdBusWidths); 1039 if (EFI_ERROR (Status)) { 1040 return Status; 1041 } 1042 1043 Private->Slot[Slot].Initialized = TRUE; 1044 1045 return Status; 1046 } 1047