1 /** @file
2 This file provides some helper functions which are specific for EMMC 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 #define EMMC_GET_STATE(x) (((x) >> 9) & 0xf)
18 #define EMMC_STATE_IDLE 0
19 #define EMMC_STATE_READY 1
20 #define EMMC_STATE_IDENT 2
21 #define EMMC_STATE_STBY 3
22 #define EMMC_STATE_TRAN 4
23 #define EMMC_STATE_DATA 5
24 #define EMMC_STATE_RCV 6
25 #define EMMC_STATE_PRG 7
26 #define EMMC_STATE_DIS 8
27 #define EMMC_STATE_BTST 9
28 #define EMMC_STATE_SLP 10
29
30 #define EMMC_CMD1_CAPACITY_LESS_THAN_2GB 0x00FF8080 // Capacity <= 2GB, byte addressing used
31 #define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8080 // Capacity > 2GB, 512-byte sector addressing used
32
33 /**
34 Send command GO_IDLE_STATE (CMD0 with argument of 0x00000000) to the device to
35 make it go to Idle State.
36
37 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
38
39 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
40 @param[in] Slot The slot number of the SD card to send the command to.
41
42 @retval EFI_SUCCESS The EMMC device is reset correctly.
43 @retval Others The device reset fails.
44
45 **/
46 EFI_STATUS
EmmcReset(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)47 EmmcReset (
48 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
49 IN UINT8 Slot
50 )
51 {
52 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
53 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
54 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
55 EFI_STATUS Status;
56
57 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
58 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
59 ZeroMem (&Packet, sizeof (Packet));
60
61 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
62 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
63 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT;
64
65 SdMmcCmdBlk.CommandIndex = EMMC_GO_IDLE_STATE;
66 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBc;
67 SdMmcCmdBlk.ResponseType = 0;
68 SdMmcCmdBlk.CommandArgument = 0;
69
70 gBS->Stall (1000);
71
72 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
73
74 return Status;
75 }
76
77 /**
78 Send command SEND_OP_COND to the EMMC device to get the data of the OCR register.
79
80 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
81
82 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
83 @param[in] Slot The slot number of the SD card to send the command to.
84 @param[in, out] Argument On input, the argument of SEND_OP_COND is to send to the device.
85 On output, the argument is the value of OCR register.
86
87 @retval EFI_SUCCESS The operation is done correctly.
88 @retval Others The operation fails.
89
90 **/
91 EFI_STATUS
EmmcGetOcr(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN OUT UINT32 * Argument)92 EmmcGetOcr (
93 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
94 IN UINT8 Slot,
95 IN OUT UINT32 *Argument
96 )
97 {
98 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
99 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
100 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
101 EFI_STATUS Status;
102
103 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
104 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
105 ZeroMem (&Packet, sizeof (Packet));
106
107 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
108 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
109 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT;
110
111 SdMmcCmdBlk.CommandIndex = EMMC_SEND_OP_COND;
112 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr;
113 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR3;
114 SdMmcCmdBlk.CommandArgument = *Argument;
115
116 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
117 if (!EFI_ERROR (Status)) {
118 //
119 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
120 //
121 *Argument = SdMmcStatusBlk.Resp0;
122 }
123
124 return Status;
125 }
126
127 /**
128 Broadcast command ALL_SEND_CID to the bus to ask all the EMMC devices to send the
129 data of their CID registers.
130
131 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
132
133 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
134 @param[in] Slot The slot number of the SD card to send the command to.
135
136 @retval EFI_SUCCESS The operation is done correctly.
137 @retval Others The operation fails.
138
139 **/
140 EFI_STATUS
EmmcGetAllCid(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)141 EmmcGetAllCid (
142 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
143 IN UINT8 Slot
144 )
145 {
146 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
147 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
148 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
149 EFI_STATUS Status;
150
151 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
152 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
153 ZeroMem (&Packet, sizeof (Packet));
154
155 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
156 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
157 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT;
158
159 SdMmcCmdBlk.CommandIndex = EMMC_ALL_SEND_CID;
160 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr;
161 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
162 SdMmcCmdBlk.CommandArgument = 0;
163
164 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
165
166 return Status;
167 }
168
169 /**
170 Send command SET_RELATIVE_ADDR to the EMMC device to assign a Relative device
171 Address (RCA).
172
173 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
174
175 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
176 @param[in] Slot The slot number of the SD card to send the command to.
177 @param[in] Rca The relative device address to be assigned.
178
179 @retval EFI_SUCCESS The operation is done correctly.
180 @retval Others The operation fails.
181
182 **/
183 EFI_STATUS
EmmcSetRca(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)184 EmmcSetRca (
185 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
186 IN UINT8 Slot,
187 IN UINT16 Rca
188 )
189 {
190 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
191 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
192 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
193 EFI_STATUS Status;
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 = EMMC_SET_RELATIVE_ADDR;
204 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
205 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
206 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
207
208 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
209
210 return Status;
211 }
212
213 /**
214 Send command SEND_CSD to the EMMC device to get the data of the CSD register.
215
216 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
217
218 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
219 @param[in] Slot The slot number of the SD card to send the command to.
220 @param[in] Rca The relative device address of selected device.
221 @param[out] Csd The buffer to store the content of the CSD register.
222 Note the caller should ignore the lowest byte of this
223 buffer as the content of this byte is meaningless even
224 if the operation succeeds.
225
226 @retval EFI_SUCCESS The operation is done correctly.
227 @retval Others The operation fails.
228
229 **/
230 EFI_STATUS
EmmcGetCsd(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT EMMC_CSD * Csd)231 EmmcGetCsd (
232 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
233 IN UINT8 Slot,
234 IN UINT16 Rca,
235 OUT EMMC_CSD *Csd
236 )
237 {
238 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
239 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
240 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
241 EFI_STATUS Status;
242
243 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
244 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
245 ZeroMem (&Packet, sizeof (Packet));
246
247 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
248 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
249 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT;
250
251 SdMmcCmdBlk.CommandIndex = EMMC_SEND_CSD;
252 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
253 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
254 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
255
256 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
257 if (!EFI_ERROR (Status)) {
258 //
259 // Copy 128bit data for CSD structure.
260 //
261 CopyMem ((VOID *)Csd + 1, &SdMmcStatusBlk.Resp0, sizeof (EMMC_CSD) - 1);
262 }
263
264 return Status;
265 }
266
267 /**
268 Send command SELECT_DESELECT_CARD to the EMMC device to select/deselect it.
269
270 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
271
272 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
273 @param[in] Slot The slot number of the SD card to send the command to.
274 @param[in] Rca The relative device address of selected device.
275
276 @retval EFI_SUCCESS The operation is done correctly.
277 @retval Others The operation fails.
278
279 **/
280 EFI_STATUS
EmmcSelect(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)281 EmmcSelect (
282 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
283 IN UINT8 Slot,
284 IN UINT16 Rca
285 )
286 {
287 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
288 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
289 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
290 EFI_STATUS Status;
291
292 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
293 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
294 ZeroMem (&Packet, sizeof (Packet));
295
296 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
297 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
298 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT;
299
300 SdMmcCmdBlk.CommandIndex = EMMC_SELECT_DESELECT_CARD;
301 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
302 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
303 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
304
305 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
306
307 return Status;
308 }
309
310 /**
311 Send command SEND_EXT_CSD to the EMMC device to get the data of the EXT_CSD register.
312
313 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
314
315 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
316 @param[in] Slot The slot number of the SD card to send the command to.
317 @param[out] ExtCsd The buffer to store the content of the EXT_CSD register.
318
319 @retval EFI_SUCCESS The operation is done correctly.
320 @retval Others The operation fails.
321
322 **/
323 EFI_STATUS
EmmcGetExtCsd(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,OUT EMMC_EXT_CSD * ExtCsd)324 EmmcGetExtCsd (
325 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
326 IN UINT8 Slot,
327 OUT EMMC_EXT_CSD *ExtCsd
328 )
329 {
330 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
331 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
332 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
333 EFI_STATUS Status;
334
335 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
336 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
337 ZeroMem (&Packet, sizeof (Packet));
338
339 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
340 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
341 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT;
342
343 SdMmcCmdBlk.CommandIndex = EMMC_SEND_EXT_CSD;
344 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
345 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
346 SdMmcCmdBlk.CommandArgument = 0x00000000;
347
348 Packet.InDataBuffer = ExtCsd;
349 Packet.InTransferLength = sizeof (EMMC_EXT_CSD);
350
351 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
352 return Status;
353 }
354
355 /**
356 Send command SWITCH to the EMMC device to switch the mode of operation of the
357 selected Device or modifies the EXT_CSD registers.
358
359 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
360
361 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
362 @param[in] Slot The slot number of the SD card to send the command to.
363 @param[in] Access The access mode of SWTICH command.
364 @param[in] Index The offset of the field to be access.
365 @param[in] Value The value to be set to the specified field of EXT_CSD register.
366 @param[in] CmdSet The value of CmdSet field of EXT_CSD register.
367
368 @retval EFI_SUCCESS The operation is done correctly.
369 @retval Others The operation fails.
370
371 **/
372 EFI_STATUS
EmmcSwitch(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 Access,IN UINT8 Index,IN UINT8 Value,IN UINT8 CmdSet)373 EmmcSwitch (
374 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
375 IN UINT8 Slot,
376 IN UINT8 Access,
377 IN UINT8 Index,
378 IN UINT8 Value,
379 IN UINT8 CmdSet
380 )
381 {
382 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
383 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
384 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
385 EFI_STATUS Status;
386
387 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
388 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
389 ZeroMem (&Packet, sizeof (Packet));
390
391 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
392 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
393 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT;
394
395 SdMmcCmdBlk.CommandIndex = EMMC_SWITCH;
396 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
397 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
398 SdMmcCmdBlk.CommandArgument = (Access << 24) | (Index << 16) | (Value << 8) | CmdSet;
399
400 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
401
402 return Status;
403 }
404
405 /**
406 Send command SEND_STATUS to the addressed EMMC device to get its status register.
407
408 Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
409
410 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
411 @param[in] Slot The slot number of the SD card to send the command to.
412 @param[in] Rca The relative device address of addressed device.
413 @param[out] DevStatus The returned device status.
414
415 @retval EFI_SUCCESS The operation is done correctly.
416 @retval Others The operation fails.
417
418 **/
419 EFI_STATUS
EmmcSendStatus(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT UINT32 * DevStatus)420 EmmcSendStatus (
421 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
422 IN UINT8 Slot,
423 IN UINT16 Rca,
424 OUT UINT32 *DevStatus
425 )
426 {
427 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
428 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
429 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
430 EFI_STATUS Status;
431
432 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
433 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
434 ZeroMem (&Packet, sizeof (Packet));
435
436 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
437 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
438 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT;
439
440 SdMmcCmdBlk.CommandIndex = EMMC_SEND_STATUS;
441 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
442 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
443 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
444
445 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
446 if (!EFI_ERROR (Status)) {
447 *DevStatus = SdMmcStatusBlk.Resp0;
448 }
449
450 return Status;
451 }
452
453 /**
454 Send command SEND_TUNING_BLOCK to the EMMC device for HS200 optimal sampling point
455 detection.
456
457 It may be sent up to 40 times until the host finishes the tuning procedure.
458
459 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 for details.
460
461 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
462 @param[in] Slot The slot number of the SD card to send the command to.
463 @param[in] BusWidth The bus width to work.
464
465 @retval EFI_SUCCESS The operation is done correctly.
466 @retval Others The operation fails.
467
468 **/
469 EFI_STATUS
EmmcSendTuningBlk(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 BusWidth)470 EmmcSendTuningBlk (
471 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
472 IN UINT8 Slot,
473 IN UINT8 BusWidth
474 )
475 {
476 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
477 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
478 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
479 EFI_STATUS Status;
480 UINT8 TuningBlock[128];
481
482 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
483 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
484 ZeroMem (&Packet, sizeof (Packet));
485
486 Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
487 Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
488 Packet.Timeout = DW_MMC_HC_GENERIC_TIMEOUT;
489
490 SdMmcCmdBlk.CommandIndex = EMMC_SEND_TUNING_BLOCK;
491 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
492 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
493 SdMmcCmdBlk.CommandArgument = 0;
494
495 Packet.InDataBuffer = TuningBlock;
496 if (BusWidth == 8) {
497 Packet.InTransferLength = sizeof (TuningBlock);
498 } else {
499 Packet.InTransferLength = 64;
500 }
501
502 Status = DwMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
503
504 return Status;
505 }
506
507 /**
508 Tunning the clock to get HS200 optimal sampling point.
509
510 Command SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the
511 tuning procedure.
512
513 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
514 Simplified Spec 3.0 Figure 2-29 for details.
515
516 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
517 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
518 @param[in] Slot The slot number of the SD card to send the command to.
519 @param[in] BusWidth The bus width to work.
520
521 @retval EFI_SUCCESS The operation is done correctly.
522 @retval Others The operation fails.
523
524 **/
525 EFI_STATUS
EmmcTuningClkForHs200(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 BusWidth)526 EmmcTuningClkForHs200 (
527 IN EFI_PCI_IO_PROTOCOL *PciIo,
528 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
529 IN UINT8 Slot,
530 IN UINT8 BusWidth
531 )
532 {
533 #if 0
534 EFI_STATUS Status;
535 UINT8 HostCtrl2;
536 UINT8 Retry;
537
538 //
539 // Notify the host that the sampling clock tuning procedure starts.
540 //
541 HostCtrl2 = BIT6;
542 Status = DwMmcHcOrMmio (PciIo, Slot, DW_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
543 if (EFI_ERROR (Status)) {
544 return Status;
545 }
546 //
547 // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
548 //
549 Retry = 0;
550 do {
551 Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
552 if (EFI_ERROR (Status)) {
553 DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
554 return Status;
555 }
556
557 Status = DwMmcHcRwMmio (PciIo, Slot, DW_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
558 if (EFI_ERROR (Status)) {
559 return Status;
560 }
561
562 if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {
563 break;
564 }
565
566 if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
567 return EFI_SUCCESS;
568 }
569 } while (++Retry < 40);
570
571 DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));
572 //
573 // Abort the tuning procedure and reset the tuning circuit.
574 //
575 HostCtrl2 = (UINT8)~(BIT6 | BIT7);
576 Status = DwMmcHcAndMmio (PciIo, Slot, DW_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
577 if (EFI_ERROR (Status)) {
578 return Status;
579 }
580 return EFI_DEVICE_ERROR;
581 #else
582 return EFI_SUCCESS;
583 #endif
584 }
585
586 /**
587 Switch the bus width to specified width.
588
589 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.9 and SD Host Controller
590 Simplified Spec 3.0 Figure 3-7 for details.
591
592 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
593 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
594 @param[in] Slot The slot number of the SD card to send the command to.
595 @param[in] Rca The relative device address to be assigned.
596 @param[in] IsDdr If TRUE, use dual data rate data simpling method. Otherwise
597 use single data rate data simpling method.
598 @param[in] BusWidth The bus width to be set, it could be 4 or 8.
599
600 @retval EFI_SUCCESS The operation is done correctly.
601 @retval Others The operation fails.
602
603 **/
604 EFI_STATUS
EmmcSwitchBusWidth(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN BOOLEAN IsDdr,IN UINT8 BusWidth)605 EmmcSwitchBusWidth (
606 IN EFI_PCI_IO_PROTOCOL *PciIo,
607 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
608 IN UINT8 Slot,
609 IN UINT16 Rca,
610 IN BOOLEAN IsDdr,
611 IN UINT8 BusWidth
612 )
613 {
614 EFI_STATUS Status;
615 UINT8 Access;
616 UINT8 Index;
617 UINT8 Value;
618 UINT8 CmdSet;
619 UINT32 DevStatus;
620
621 //
622 // Write Byte, the Value field is written into the byte pointed by Index.
623 //
624 Access = 0x03;
625 Index = OFFSET_OF (EMMC_EXT_CSD, BusWidth);
626 if (BusWidth == 1) {
627 Value = 0;
628 } else {
629 if (BusWidth == 4) {
630 Value = 1;
631 } else if (BusWidth == 8) {
632 Value = 2;
633 } else {
634 return EFI_INVALID_PARAMETER;
635 }
636
637 if (IsDdr) {
638 Value += 4;
639 }
640 }
641
642 CmdSet = 0;
643 Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
644 if (EFI_ERROR (Status)) {
645 DEBUG ((DEBUG_ERROR, "EmmcSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth, Status));
646 return Status;
647 }
648
649 do {
650 Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
651 if (EFI_ERROR (Status)) {
652 DEBUG ((DEBUG_ERROR, "EmmcSwitchBusWidth: Send status fails with %r\n", Status));
653 return Status;
654 }
655 //
656 // Check the switch operation is really successful or not.
657 //
658 } while ((DevStatus & 0xf) == EMMC_STATE_PRG);
659
660 Status = DwMmcHcSetBusWidth (PciIo, Slot, IsDdr, BusWidth);
661 if (EFI_ERROR (Status)) {
662 return Status;
663 }
664
665 return Status;
666 }
667
668 /**
669 Switch the clock frequency to the specified value.
670
671 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6 and SD Host Controller
672 Simplified Spec 3.0 Figure 3-3 for details.
673
674 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
675 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
676 @param[in] Slot The slot number of the SD card to send the command to.
677 @param[in] Rca The relative device address to be assigned.
678 @param[in] HsTiming The value to be written to HS_TIMING field of EXT_CSD register.
679 @param[in] ClockFreq The max clock frequency to be set, the unit is MHz.
680
681 @retval EFI_SUCCESS The operation is done correctly.
682 @retval Others The operation fails.
683
684 **/
685 EFI_STATUS
EmmcSwitchClockFreq(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT8 HsTiming,IN UINT32 ClockFreq)686 EmmcSwitchClockFreq (
687 IN EFI_PCI_IO_PROTOCOL *PciIo,
688 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
689 IN UINT8 Slot,
690 IN UINT16 Rca,
691 IN UINT8 HsTiming,
692 IN UINT32 ClockFreq
693 )
694 {
695 EFI_STATUS Status;
696 UINT8 Access;
697 UINT8 Index;
698 UINT8 Value;
699 UINT8 CmdSet;
700 UINT32 DevStatus;
701 DW_MMC_HC_PRIVATE_DATA *Private;
702
703 Private = DW_MMC_HC_PRIVATE_FROM_THIS (PassThru);
704 //
705 // Write Byte, the Value field is written into the byte pointed by Index.
706 //
707 Access = 0x03;
708 Index = OFFSET_OF (EMMC_EXT_CSD, HsTiming);
709 Value = HsTiming;
710 CmdSet = 0;
711
712 Status = EmmcSwitch (PassThru, Slot, Access, Index, Value, CmdSet);
713 if (EFI_ERROR (Status)) {
714 DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Switch to hstiming %d fails with %r\n", HsTiming, Status));
715 return Status;
716 }
717
718 Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
719 if (EFI_ERROR (Status)) {
720 DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: Send status fails with %r\n", Status));
721 return Status;
722 }
723 //
724 // Check the switch operation is really successful or not.
725 //
726 if ((DevStatus & BIT7) != 0) {
727 DEBUG ((DEBUG_ERROR, "EmmcSwitchClockFreq: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));
728 return EFI_DEVICE_ERROR;
729 }
730 //
731 // Convert the clock freq unit from MHz to KHz.
732 //
733 Status = DwMmcHcClockSupply (PciIo, Slot, ClockFreq * 1000, Private->Capability[Slot]);
734
735 return Status;
736 }
737
738 /**
739 Switch to the High Speed timing according to request.
740
741 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
742 Simplified Spec 3.0 Figure 2-29 for details.
743
744 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
745 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
746 @param[in] Slot The slot number of the SD card to send the command to.
747 @param[in] Rca The relative device address to be assigned.
748 @param[in] ClockFreq The max clock frequency to be set.
749 @param[in] IsDdr If TRUE, use dual data rate data simpling method. Otherwise
750 use single data rate data simpling method.
751 @param[in] BusWidth The bus width to be set, it could be 4 or 8.
752
753 @retval EFI_SUCCESS The operation is done correctly.
754 @retval Others The operation fails.
755
756 **/
757 EFI_STATUS
EmmcSwitchToHighSpeed(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT32 ClockFreq,IN BOOLEAN IsDdr,IN UINT8 BusWidth)758 EmmcSwitchToHighSpeed (
759 IN EFI_PCI_IO_PROTOCOL *PciIo,
760 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
761 IN UINT8 Slot,
762 IN UINT16 Rca,
763 IN UINT32 ClockFreq,
764 IN BOOLEAN IsDdr,
765 IN UINT8 BusWidth
766 )
767 {
768 EFI_STATUS Status;
769 UINT8 HsTiming;
770
771 HsTiming = 1;
772 Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, ClockFreq);
773 if (EFI_ERROR (Status)) {
774 return Status;
775 }
776 Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);
777 if (EFI_ERROR (Status)) {
778 return Status;
779 }
780 return EFI_SUCCESS;
781 }
782
783 /**
784 Switch to the HS200 timing according to request.
785
786 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
787 Simplified Spec 3.0 Figure 2-29 for details.
788
789 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
790 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
791 @param[in] Slot The slot number of the SD card to send the command to.
792 @param[in] Rca The relative device address to be assigned.
793 @param[in] ClockFreq The max clock frequency to be set.
794 @param[in] BusWidth The bus width to be set, it could be 4 or 8.
795
796 @retval EFI_SUCCESS The operation is done correctly.
797 @retval Others The operation fails.
798
799 **/
800 EFI_STATUS
EmmcSwitchToHS200(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT32 ClockFreq,IN UINT8 BusWidth)801 EmmcSwitchToHS200 (
802 IN EFI_PCI_IO_PROTOCOL *PciIo,
803 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
804 IN UINT8 Slot,
805 IN UINT16 Rca,
806 IN UINT32 ClockFreq,
807 IN UINT8 BusWidth
808 )
809 {
810 return EFI_SUCCESS;
811 }
812
813 /**
814 Switch the high speed timing according to request.
815
816 Refer to EMMC Electrical Standard Spec 5.1 Section 6.6.8 and SD Host Controller
817 Simplified Spec 3.0 Figure 2-29 for details.
818
819 @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
820 @param[in] PassThru A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
821 @param[in] Slot The slot number of the SD card to send the command to.
822 @param[in] Rca The relative device address to be assigned.
823
824 @retval EFI_SUCCESS The operation is done correctly.
825 @retval Others The operation fails.
826
827 **/
828 EFI_STATUS
EmmcSetBusMode(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)829 EmmcSetBusMode (
830 IN EFI_PCI_IO_PROTOCOL *PciIo,
831 IN EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru,
832 IN UINT8 Slot,
833 IN UINT16 Rca
834 )
835 {
836 EFI_STATUS Status;
837 EMMC_CSD Csd;
838 EMMC_EXT_CSD ExtCsd;
839 UINT8 HsTiming;
840 BOOLEAN IsDdr;
841 UINT32 DevStatus;
842 UINT32 ClockFreq;
843 UINT8 BusWidth;
844 DW_MMC_HC_PRIVATE_DATA *Private;
845
846 Private = DW_MMC_HC_PRIVATE_FROM_THIS (PassThru);
847 ASSERT (Private->Capability[Slot].BaseClkFreq != 0);
848
849 Status = EmmcGetCsd (PassThru, Slot, Rca, &Csd);
850 if (EFI_ERROR (Status)) {
851 DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetCsd fails with %r\n", Status));
852 return Status;
853 }
854
855 Status = EmmcSelect (PassThru, Slot, Rca);
856 if (EFI_ERROR (Status)) {
857 DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: Select fails with %r\n", Status));
858 return Status;
859 }
860
861 do {
862 Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
863 if (EFI_ERROR (Status)) {
864 DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: Get Status fails with %r\n", Status));
865 return Status;
866 }
867 } while (EMMC_GET_STATE (DevStatus) != EMMC_STATE_TRAN);
868
869 BusWidth = 1;
870 Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, FALSE, BusWidth);
871 if (EFI_ERROR (Status)) {
872 return Status;
873 }
874
875 BusWidth = Private->Capability[Slot].BusWidth;
876 //
877 // Get Deivce_Type from EXT_CSD register.
878 //
879 Status = EmmcGetExtCsd (PassThru, Slot, &ExtCsd);
880 if (EFI_ERROR (Status)) {
881 DEBUG ((DEBUG_ERROR, "EmmcSetBusMode: GetExtCsd fails with %r\n", Status));
882 return Status;
883 }
884
885 //
886 // Calculate supported bus speed/bus width/clock frequency.
887 //
888 HsTiming = 0;
889 IsDdr = FALSE;
890 ClockFreq = 0;
891 if (((ExtCsd.DeviceType & (BIT4 | BIT5)) != 0) && (Private->Capability[Slot].Sdr104 != 0)) {
892 HsTiming = 2;
893 IsDdr = FALSE;
894 ClockFreq = 200;
895 } else if (((ExtCsd.DeviceType & (BIT2 | BIT3)) != 0) && (Private->Capability[Slot].Ddr50 != 0)) {
896 HsTiming = 1;
897 IsDdr = TRUE;
898 ClockFreq = 52;
899 } else if (((ExtCsd.DeviceType & BIT1) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
900 HsTiming = 1;
901 IsDdr = FALSE;
902 ClockFreq = 52;
903 } else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
904 HsTiming = 1;
905 IsDdr = FALSE;
906 ClockFreq = 26;
907 }
908
909 if ((ClockFreq == 0) || (HsTiming == 0)) {
910 //
911 // Continue using default setting.
912 //
913 return EFI_SUCCESS;
914 }
915
916 DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ? "TRUE":"FALSE"));
917
918 if (HsTiming == 2) {
919 //
920 // Execute HS200 timing switch procedure
921 //
922 Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
923 } else {
924 //
925 // Execute High Speed timing switch procedure
926 //
927 Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
928 }
929
930 DEBUG ((DEBUG_INFO, "EmmcSetBusMode: Switch to %a %r\n", (HsTiming == 3) ? "HS400" : ((HsTiming == 2) ? "HS200" : "HighSpeed"), Status));
931
932 return Status;
933 }
934
935 /**
936 Execute EMMC device identification procedure.
937
938 Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
939
940 @param[in] Private A pointer to the DW_MMC_HC_PRIVATE_DATA instance.
941 @param[in] Slot The slot number of the SD card to send the command to.
942
943 @retval EFI_SUCCESS There is a EMMC card.
944 @retval Others There is not a EMMC card.
945
946 **/
947 EFI_STATUS
EmmcIdentification(IN DW_MMC_HC_PRIVATE_DATA * Private,IN UINT8 Slot)948 EmmcIdentification (
949 IN DW_MMC_HC_PRIVATE_DATA *Private,
950 IN UINT8 Slot
951 )
952 {
953 EFI_STATUS Status;
954 EFI_PCI_IO_PROTOCOL *PciIo;
955 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
956 UINT32 Ocr;
957 UINT16 Rca;
958 UINT32 DevStatus;
959 UINT32 Timeout;
960
961 PciIo = Private->PciIo;
962 PassThru = &Private->PassThru;
963
964 Status = EmmcReset (PassThru, Slot);
965 if (EFI_ERROR (Status)) {
966 DEBUG ((DEBUG_INFO, "EmmcIdentification: Executing Cmd0 fails with %r\n", Status));
967 return Status;
968 }
969
970 Timeout = 100;
971 do {
972 Ocr = EMMC_CMD1_CAPACITY_GREATER_THAN_2GB;
973 Status = EmmcGetOcr (PassThru, Slot, &Ocr);
974 if (EFI_ERROR (Status)) {
975 DEBUG ((DEBUG_INFO, "EmmcIdentification: Executing Cmd1 fails with %r\n", Status));
976 return Status;
977 }
978 if (--Timeout <= 0) {
979 return EFI_DEVICE_ERROR;
980 }
981 MicroSecondDelay (100);
982 } while ((Ocr & BIT31) == 0);
983
984 Status = EmmcGetAllCid (PassThru, Slot);
985 if (EFI_ERROR (Status)) {
986 DEBUG ((DEBUG_INFO, "EmmcIdentification: Executing Cmd2 fails with %r\n", Status));
987 return Status;
988 }
989 //
990 // Slot starts from 0 and valid RCA starts from 1.
991 // Here we takes a simple formula to calculate the RCA.
992 // Don't support multiple devices on the slot, that is
993 // shared bus slot feature.
994 //
995 Rca = Slot + 1;
996 Status = EmmcSetRca (PassThru, Slot, Rca);
997 if (EFI_ERROR (Status)) {
998 DEBUG ((DEBUG_INFO, "EmmcIdentification: Executing Cmd3 fails with %r\n", Status));
999 return Status;
1000 }
1001 //
1002 // Enter Data Tranfer Mode.
1003 //
1004 DEBUG ((DEBUG_INFO, "EmmcIdentification: Found a EMMC device at slot [%d], RCA [%d]\n", Slot, Rca));
1005 Private->Slot[Slot].CardType = EmmcCardType;
1006
1007 Status = EmmcSetBusMode (PciIo, PassThru, Slot, Rca);
1008 if (EFI_ERROR (Status)) {
1009 return Status;
1010 }
1011
1012 //
1013 // Exit DATA Mode.
1014 //
1015 do {
1016 Status = EmmcSendStatus (PassThru, Slot, Rca, &DevStatus);
1017 if (EFI_ERROR (Status)) {
1018 DEBUG ((DEBUG_INFO, "EmmcSwitchBusWidth: Send status fails with %r\n", Status));
1019 return Status;
1020 }
1021 } while ((DevStatus & 0xf) == EMMC_STATE_DATA);
1022
1023 return Status;
1024 }
1025