1 /** @file
2   This file provides some helper functions which are specific for SD card device.
3 
4   Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
5   Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "SdMmcPciHcDxe.h"
11 
12 /**
13   Send command GO_IDLE_STATE to the device to make it go to Idle State.
14 
15   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
16 
17   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
18   @param[in] Slot           The slot number of the SD card to send the command to.
19 
20   @retval EFI_SUCCESS       The SD device is reset correctly.
21   @retval Others            The device reset fails.
22 
23 **/
24 EFI_STATUS
SdCardReset(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)25 SdCardReset (
26   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
27   IN UINT8                              Slot
28   )
29 {
30   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
31   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
32   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
33   EFI_STATUS                            Status;
34 
35   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
36   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
37   ZeroMem (&Packet, sizeof (Packet));
38 
39   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
40   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
41   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
42 
43   SdMmcCmdBlk.CommandIndex = SD_GO_IDLE_STATE;
44   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBc;
45 
46   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
47 
48   return Status;
49 }
50 
51 /**
52   Send command SEND_IF_COND to the device to inquiry the SD Memory Card interface
53   condition.
54 
55   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
56 
57   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
58   @param[in] Slot           The slot number of the SD card to send the command to.
59   @param[in] SupplyVoltage  The supplied voltage by the host.
60   @param[in] CheckPattern   The check pattern to be sent to the device.
61 
62   @retval EFI_SUCCESS       The operation is done correctly.
63   @retval Others            The operation fails.
64 
65 **/
66 EFI_STATUS
SdCardVoltageCheck(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT8 SupplyVoltage,IN UINT8 CheckPattern)67 SdCardVoltageCheck (
68   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
69   IN UINT8                              Slot,
70   IN UINT8                              SupplyVoltage,
71   IN UINT8                              CheckPattern
72   )
73 {
74   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
75   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
76   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
77   EFI_STATUS                            Status;
78 
79   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
80   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
81   ZeroMem (&Packet, sizeof (Packet));
82 
83   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
84   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
85   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
86 
87   SdMmcCmdBlk.CommandIndex = SD_SEND_IF_COND;
88   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
89   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR7;
90   SdMmcCmdBlk.CommandArgument = (SupplyVoltage << 8) | CheckPattern;
91 
92   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
93 
94   if (!EFI_ERROR (Status)) {
95     if (SdMmcStatusBlk.Resp0 != SdMmcCmdBlk.CommandArgument) {
96       return EFI_DEVICE_ERROR;
97     }
98   }
99 
100   return Status;
101 }
102 
103 /**
104   Send command SDIO_SEND_OP_COND to the device to see whether it is SDIO device.
105 
106   Refer to SDIO Simplified Spec 3 Section 3.2 for details.
107 
108   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
109   @param[in] Slot           The slot number of the SD card to send the command to.
110   @param[in] VoltageWindow  The supply voltage window.
111   @param[in] S18R           The boolean to show if it should switch to 1.8v.
112 
113   @retval EFI_SUCCESS       The operation is done correctly.
114   @retval Others            The operation fails.
115 
116 **/
117 EFI_STATUS
SdioSendOpCond(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT32 VoltageWindow,IN BOOLEAN S18R)118 SdioSendOpCond (
119   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
120   IN UINT8                              Slot,
121   IN UINT32                             VoltageWindow,
122   IN BOOLEAN                            S18R
123   )
124 {
125   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
126   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
127   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
128   EFI_STATUS                            Status;
129   UINT32                                Switch;
130 
131   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
132   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
133   ZeroMem (&Packet, sizeof (Packet));
134 
135   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
136   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
137   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
138 
139   SdMmcCmdBlk.CommandIndex = SDIO_SEND_OP_COND;
140   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
141   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR4;
142 
143   Switch = S18R ? BIT24 : 0;
144 
145   SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch;
146 
147   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
148 
149   return Status;
150 }
151 
152 /**
153   Send command SD_SEND_OP_COND to the device to see whether it is SDIO device.
154 
155   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
156 
157   @param[in]  PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
158   @param[in]  Slot           The slot number of the SD card to send the command to.
159   @param[in]  Rca            The relative device address of addressed device.
160   @param[in]  VoltageWindow  The supply voltage window.
161   @param[in]  S18R           The boolean to show if it should switch to 1.8v.
162   @param[in]  Xpc            The boolean to show if it should provide 0.36w power control.
163   @param[in]  Hcs            The boolean to show if it support host capacity info.
164   @param[out] Ocr            The buffer to store returned OCR register value.
165 
166   @retval EFI_SUCCESS        The operation is done correctly.
167   @retval Others             The operation fails.
168 
169 **/
170 EFI_STATUS
SdCardSendOpCond(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT32 VoltageWindow,IN BOOLEAN S18R,IN BOOLEAN Xpc,IN BOOLEAN Hcs,OUT UINT32 * Ocr)171 SdCardSendOpCond (
172   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
173   IN     UINT8                          Slot,
174   IN     UINT16                         Rca,
175   IN     UINT32                         VoltageWindow,
176   IN     BOOLEAN                        S18R,
177   IN     BOOLEAN                        Xpc,
178   IN     BOOLEAN                        Hcs,
179      OUT UINT32                         *Ocr
180   )
181 {
182   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
183   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
184   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
185   EFI_STATUS                            Status;
186   UINT32                                Switch;
187   UINT32                                MaxPower;
188   UINT32                                HostCapacity;
189 
190   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
191   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
192   ZeroMem (&Packet, sizeof (Packet));
193 
194   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
195   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
196   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
197 
198   SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
199   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
200   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
201   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
202 
203   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
204   if (EFI_ERROR (Status)) {
205     return Status;
206   }
207 
208   SdMmcCmdBlk.CommandIndex = SD_SEND_OP_COND;
209   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
210   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR3;
211 
212   Switch       = S18R ? BIT24 : 0;
213   MaxPower     = Xpc ? BIT28 : 0;
214   HostCapacity = Hcs ? BIT30 : 0;
215 
216   SdMmcCmdBlk.CommandArgument = (VoltageWindow & 0xFFFFFF) | Switch | MaxPower | HostCapacity;
217 
218   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
219   if (!EFI_ERROR (Status)) {
220     //
221     // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
222     //
223     *Ocr = SdMmcStatusBlk.Resp0;
224   }
225 
226   return Status;
227 }
228 
229 /**
230   Broadcast command ALL_SEND_CID to the bus to ask all the SD devices to send the
231   data of their CID registers.
232 
233   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
234 
235   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
236   @param[in] Slot           The slot number of the SD card to send the command to.
237 
238   @retval EFI_SUCCESS       The operation is done correctly.
239   @retval Others            The operation fails.
240 
241 **/
242 EFI_STATUS
SdCardAllSendCid(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)243 SdCardAllSendCid (
244   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
245   IN UINT8                              Slot
246   )
247 {
248   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
249   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
250   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
251   EFI_STATUS                            Status;
252 
253   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
254   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
255   ZeroMem (&Packet, sizeof (Packet));
256 
257   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
258   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
259   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
260 
261   SdMmcCmdBlk.CommandIndex = SD_ALL_SEND_CID;
262   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
263   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
264 
265   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
266 
267   return Status;
268 }
269 
270 /**
271   Send command SET_RELATIVE_ADDR to the SD device to assign a Relative device
272   Address (RCA).
273 
274   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
275 
276   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
277   @param[in]  Slot          The slot number of the SD card to send the command to.
278   @param[out] Rca           The relative device address to assign.
279 
280   @retval EFI_SUCCESS       The operation is done correctly.
281   @retval Others            The operation fails.
282 
283 **/
284 EFI_STATUS
SdCardSetRca(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,OUT UINT16 * Rca)285 SdCardSetRca (
286   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
287   IN     UINT8                          Slot,
288      OUT UINT16                         *Rca
289   )
290 {
291   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
292   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
293   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
294   EFI_STATUS                            Status;
295 
296   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
297   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
298   ZeroMem (&Packet, sizeof (Packet));
299 
300   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
301   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
302   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
303 
304   SdMmcCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR;
305   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeBcr;
306   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR6;
307 
308   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
309   if (!EFI_ERROR (Status)) {
310     *Rca = (UINT16)(SdMmcStatusBlk.Resp0 >> 16);
311   }
312 
313   return Status;
314 }
315 
316 /**
317   Send command SELECT_DESELECT_CARD to the SD device to select/deselect it.
318 
319   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
320 
321   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
322   @param[in]  Slot          The slot number of the SD card to send the command to.
323   @param[in]  Rca           The relative device address of selected device.
324 
325   @retval EFI_SUCCESS       The operation is done correctly.
326   @retval Others            The operation fails.
327 
328 **/
329 EFI_STATUS
SdCardSelect(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca)330 SdCardSelect (
331   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
332   IN UINT8                              Slot,
333   IN UINT16                             Rca
334   )
335 {
336   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
337   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
338   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
339   EFI_STATUS                            Status;
340 
341   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
342   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
343   ZeroMem (&Packet, sizeof (Packet));
344 
345   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
346   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
347   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
348 
349   SdMmcCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD;
350   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
351   if (Rca != 0) {
352     SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
353   }
354   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
355 
356   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
357 
358   return Status;
359 }
360 
361 /**
362   Send command VOLTAGE_SWITCH to the SD device to switch the voltage of the device.
363 
364   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
365 
366   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
367   @param[in]  Slot          The slot number of the SD card to send the command to.
368 
369   @retval EFI_SUCCESS       The operation is done correctly.
370   @retval Others            The operation fails.
371 
372 **/
373 EFI_STATUS
SdCardVoltageSwitch(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)374 SdCardVoltageSwitch (
375   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
376   IN UINT8                              Slot
377   )
378 {
379   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
380   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
381   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
382   EFI_STATUS                            Status;
383 
384   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
385   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
386   ZeroMem (&Packet, sizeof (Packet));
387 
388   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
389   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
390   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
391 
392   SdMmcCmdBlk.CommandIndex = SD_VOLTAGE_SWITCH;
393   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
394   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
395   SdMmcCmdBlk.CommandArgument = 0;
396 
397   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
398 
399   return Status;
400 }
401 
402 /**
403   Send command SET_BUS_WIDTH to the SD device to set the bus width.
404 
405   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
406 
407   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
408   @param[in] Slot           The slot number of the SD card to send the command to.
409   @param[in] Rca            The relative device address of addressed device.
410   @param[in] BusWidth       The bus width to be set, it could be 1 or 4.
411 
412   @retval EFI_SUCCESS       The operation is done correctly.
413   @retval Others            The operation fails.
414 
415 **/
416 EFI_STATUS
SdCardSetBusWidth(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT8 BusWidth)417 SdCardSetBusWidth (
418   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
419   IN UINT8                              Slot,
420   IN UINT16                             Rca,
421   IN UINT8                              BusWidth
422   )
423 {
424   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
425   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
426   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
427   EFI_STATUS                            Status;
428   UINT8                                 Value;
429 
430   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
431   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
432   ZeroMem (&Packet, sizeof (Packet));
433 
434   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
435   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
436   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
437 
438   SdMmcCmdBlk.CommandIndex = SD_APP_CMD;
439   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
440   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
441   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
442 
443   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
444   if (EFI_ERROR (Status)) {
445     return Status;
446   }
447 
448   SdMmcCmdBlk.CommandIndex = SD_SET_BUS_WIDTH;
449   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
450   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
451 
452   if (BusWidth == 1) {
453     Value = 0;
454   } else if (BusWidth == 4) {
455     Value = 2;
456   } else {
457     return EFI_INVALID_PARAMETER;
458   }
459 
460   SdMmcCmdBlk.CommandArgument = Value & 0x3;
461 
462   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
463   return Status;
464 }
465 
466 /**
467   Send command SWITCH_FUNC to the SD device to check switchable function or switch card function.
468 
469   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
470 
471   @param[in]  PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
472   @param[in]  Slot           The slot number of the SD card to send the command to.
473   @param[in]  BusTiming      Target bus timing based on which access group value will be set.
474   @param[in]  CommandSystem  The value for command set group.
475   @param[in]  DriverStrength The value for driver strength group.
476   @param[in]  PowerLimit     The value for power limit group.
477   @param[in]  Mode           Switch or check function.
478   @param[out] SwitchResp     The return switch function status.
479 
480   @retval EFI_SUCCESS       The operation is done correctly.
481   @retval Others            The operation fails.
482 
483 **/
484 EFI_STATUS
SdCardSwitch(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN SD_MMC_BUS_MODE BusTiming,IN UINT8 CommandSystem,IN SD_DRIVER_STRENGTH_TYPE DriverStrength,IN UINT8 PowerLimit,IN BOOLEAN Mode,OUT UINT8 * SwitchResp)485 SdCardSwitch (
486   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
487   IN     UINT8                          Slot,
488   IN     SD_MMC_BUS_MODE                BusTiming,
489   IN     UINT8                          CommandSystem,
490   IN     SD_DRIVER_STRENGTH_TYPE        DriverStrength,
491   IN     UINT8                          PowerLimit,
492   IN     BOOLEAN                        Mode,
493      OUT UINT8                          *SwitchResp
494   )
495 {
496   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
497   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
498   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
499   EFI_STATUS                            Status;
500   UINT32                                ModeValue;
501   UINT8                                 AccessMode;
502 
503   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
504   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
505   ZeroMem (&Packet, sizeof (Packet));
506 
507   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
508   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
509   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
510 
511   SdMmcCmdBlk.CommandIndex = SD_SWITCH_FUNC;
512   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
513   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
514 
515   ModeValue = Mode ? BIT31 : 0;
516 
517   switch (BusTiming) {
518     case SdMmcUhsDdr50:
519       AccessMode = 0x4;
520       break;
521     case SdMmcUhsSdr104:
522       AccessMode = 0x3;
523       break;
524     case SdMmcUhsSdr50:
525       AccessMode = 0x2;
526       break;
527     case SdMmcUhsSdr25:
528     case SdMmcSdHs:
529       AccessMode = 0x1;
530       break;
531     case SdMmcUhsSdr12:
532     case SdMmcSdDs:
533       AccessMode = 0;
534       break;
535     default:
536       AccessMode = 0xF;
537   }
538 
539   SdMmcCmdBlk.CommandArgument = (AccessMode & 0xF) | ((CommandSystem & 0xF) << 4) | \
540                                 ((DriverStrength & 0xF) << 8) | ((PowerLimit & 0xF) << 12) | \
541                                 ModeValue;
542 
543   Packet.InDataBuffer     = SwitchResp;
544   Packet.InTransferLength = 64;
545 
546   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
547   if (EFI_ERROR (Status)) {
548     return Status;
549   }
550 
551   if (Mode) {
552     if ((((AccessMode & 0xF) != 0xF) && ((SwitchResp[16] & 0xF) != AccessMode)) ||
553         (((CommandSystem & 0xF) != 0xF) && (((SwitchResp[16] >> 4) & 0xF) != CommandSystem)) ||
554         (((DriverStrength & 0xF) != 0xF) && ((SwitchResp[15] & 0xF) != DriverStrength)) ||
555         (((PowerLimit & 0xF) != 0xF) && (((SwitchResp[15] >> 4) & 0xF) != PowerLimit))) {
556       return EFI_DEVICE_ERROR;
557     }
558   }
559 
560   return Status;
561 }
562 
563 /**
564   Send command SEND_STATUS to the addressed SD device to get its status register.
565 
566   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
567 
568   @param[in]  PassThru      A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
569   @param[in]  Slot          The slot number of the SD card to send the command to.
570   @param[in]  Rca           The relative device address of addressed device.
571   @param[out] DevStatus     The returned device status.
572 
573   @retval EFI_SUCCESS       The operation is done correctly.
574   @retval Others            The operation fails.
575 
576 **/
577 EFI_STATUS
SdCardSendStatus(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,OUT UINT32 * DevStatus)578 SdCardSendStatus (
579   IN     EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru,
580   IN     UINT8                          Slot,
581   IN     UINT16                         Rca,
582      OUT UINT32                         *DevStatus
583   )
584 {
585   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
586   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
587   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
588   EFI_STATUS                            Status;
589 
590   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
591   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
592   ZeroMem (&Packet, sizeof (Packet));
593 
594   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
595   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
596   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
597 
598   SdMmcCmdBlk.CommandIndex = SD_SEND_STATUS;
599   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAc;
600   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
601   SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
602 
603   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
604   if (!EFI_ERROR (Status)) {
605     *DevStatus = SdMmcStatusBlk.Resp0;
606   }
607 
608   return Status;
609 }
610 
611 /**
612   Send command SEND_TUNING_BLOCK to the SD device for HS200 optimal sampling point
613   detection.
614 
615   It may be sent up to 40 times until the host finishes the tuning procedure.
616 
617   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
618 
619   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
620   @param[in] Slot           The slot number of the SD card to send the command to.
621 
622   @retval EFI_SUCCESS       The operation is done correctly.
623   @retval Others            The operation fails.
624 
625 **/
626 EFI_STATUS
SdCardSendTuningBlk(IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)627 SdCardSendTuningBlk (
628   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
629   IN UINT8                              Slot
630   )
631 {
632   EFI_SD_MMC_COMMAND_BLOCK              SdMmcCmdBlk;
633   EFI_SD_MMC_STATUS_BLOCK               SdMmcStatusBlk;
634   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   Packet;
635   EFI_STATUS                            Status;
636   UINT8                                 TuningBlock[64];
637 
638   ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
639   ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
640   ZeroMem (&Packet, sizeof (Packet));
641 
642   Packet.SdMmcCmdBlk    = &SdMmcCmdBlk;
643   Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
644   Packet.Timeout        = SD_MMC_HC_GENERIC_TIMEOUT;
645 
646   SdMmcCmdBlk.CommandIndex = SD_SEND_TUNING_BLOCK;
647   SdMmcCmdBlk.CommandType  = SdMmcCommandTypeAdtc;
648   SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
649   SdMmcCmdBlk.CommandArgument = 0;
650 
651   Packet.InDataBuffer     = TuningBlock;
652   Packet.InTransferLength = sizeof (TuningBlock);
653 
654   Status = SdMmcPassThruPassThru (PassThru, Slot, &Packet, NULL);
655 
656   return Status;
657 }
658 
659 /**
660   Tunning the sampling point of SDR104 or SDR50 bus speed mode.
661 
662   Command SD_SEND_TUNING_BLOCK may be sent up to 40 times until the host finishes the
663   tuning procedure.
664 
665   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and
666   SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.
667 
668   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
669   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
670   @param[in] Slot           The slot number of the SD card to send the command to.
671 
672   @retval EFI_SUCCESS       The operation is done correctly.
673   @retval Others            The operation fails.
674 
675 **/
676 EFI_STATUS
SdCardTuningClock(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot)677 SdCardTuningClock (
678   IN EFI_PCI_IO_PROTOCOL                *PciIo,
679   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
680   IN UINT8                              Slot
681   )
682 {
683   EFI_STATUS          Status;
684   UINT8               HostCtrl2;
685   UINT8               Retry;
686 
687   //
688   // Notify the host that the sampling clock tuning procedure starts.
689   //
690   HostCtrl2 = BIT6;
691   Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
692   if (EFI_ERROR (Status)) {
693     return Status;
694   }
695   //
696   // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
697   //
698   Retry = 0;
699   do {
700     Status = SdCardSendTuningBlk (PassThru, Slot);
701     if (EFI_ERROR (Status)) {
702       DEBUG ((DEBUG_ERROR, "SdCardSendTuningBlk: Send tuning block fails with %r\n", Status));
703       return Status;
704     }
705 
706     Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
707     if (EFI_ERROR (Status)) {
708       return Status;
709     }
710 
711     if ((HostCtrl2 & (BIT6 | BIT7)) == 0) {
712       break;
713     }
714     if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
715       return EFI_SUCCESS;
716     }
717   } while (++Retry < 40);
718 
719   DEBUG ((DEBUG_ERROR, "SdCardTuningClock: Send tuning block fails at %d times with HostCtrl2 %02x\n", Retry, HostCtrl2));
720   //
721   // Abort the tuning procedure and reset the tuning circuit.
722   //
723   HostCtrl2 = (UINT8)~(BIT6 | BIT7);
724   Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
725   if (EFI_ERROR (Status)) {
726     return Status;
727   }
728   return EFI_DEVICE_ERROR;
729 }
730 
731 /**
732   Switch the bus width to specified width.
733 
734   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and
735   SD Host Controller Simplified Spec 3.0 section Figure 3-7 for details.
736 
737   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
738   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
739   @param[in] Slot           The slot number of the SD card to send the command to.
740   @param[in] Rca            The relative device address to be assigned.
741   @param[in] BusWidth       The bus width to be set, it could be 4 or 8.
742 
743   @retval EFI_SUCCESS       The operation is done correctly.
744   @retval Others            The operation fails.
745 
746 **/
747 EFI_STATUS
SdCardSwitchBusWidth(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN UINT8 BusWidth)748 SdCardSwitchBusWidth (
749   IN EFI_PCI_IO_PROTOCOL                *PciIo,
750   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
751   IN UINT8                              Slot,
752   IN UINT16                             Rca,
753   IN UINT8                              BusWidth
754   )
755 {
756   EFI_STATUS          Status;
757   UINT32              DevStatus;
758 
759   Status = SdCardSetBusWidth (PassThru, Slot, Rca, BusWidth);
760   if (EFI_ERROR (Status)) {
761     DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Switch to bus width %d fails with %r\n", BusWidth, Status));
762     return Status;
763   }
764 
765   Status = SdCardSendStatus (PassThru, Slot, Rca, &DevStatus);
766   if (EFI_ERROR (Status)) {
767     DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: Send status fails with %r\n", Status));
768     return Status;
769   }
770   //
771   // Check the switch operation is really successful or not.
772   //
773   if ((DevStatus >> 16) != 0) {
774     DEBUG ((DEBUG_ERROR, "SdCardSwitchBusWidth: The switch operation fails as DevStatus is 0x%08x\n", DevStatus));
775     return EFI_DEVICE_ERROR;
776   }
777 
778   Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);
779 
780   return Status;
781 }
782 
783 /**
784   Check if passed BusTiming is supported in both controller and card.
785 
786   @param[in] Private                  Pointer to controller private data
787   @param[in] SlotIndex                Index of the slot in the controller
788   @param[in] CardSupportedBusTimings  Bitmask indicating which bus timings are supported by card
789   @param[in] IsInUhsI                 Flag indicating if link is in UHS-I
790 
791   @retval TRUE  Both card and controller support given BusTiming
792   @retval FALSE Card or controller doesn't support given BusTiming
793 **/
794 BOOLEAN
SdIsBusTimingSupported(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN UINT8 CardSupportedBusTimings,IN BOOLEAN IsInUhsI,IN SD_MMC_BUS_MODE BusTiming)795 SdIsBusTimingSupported (
796   IN SD_MMC_HC_PRIVATE_DATA   *Private,
797   IN UINT8                    SlotIndex,
798   IN UINT8                    CardSupportedBusTimings,
799   IN BOOLEAN                  IsInUhsI,
800   IN SD_MMC_BUS_MODE          BusTiming
801   )
802 {
803   SD_MMC_HC_SLOT_CAP           *Capability;
804 
805   Capability = &Private->Capability[SlotIndex];
806 
807   if (IsInUhsI) {
808     switch (BusTiming) {
809       case SdMmcUhsSdr104:
810         if ((Capability->Sdr104 != 0) && ((CardSupportedBusTimings & BIT3) != 0)) {
811           return TRUE;
812         }
813         break;
814       case SdMmcUhsDdr50:
815         if ((Capability->Ddr50 != 0) && ((CardSupportedBusTimings & BIT4) != 0)) {
816           return TRUE;
817         }
818         break;
819       case SdMmcUhsSdr50:
820         if ((Capability->Sdr50 != 0) && ((CardSupportedBusTimings & BIT2) != 0)) {
821           return TRUE;
822         }
823         break;
824       case SdMmcUhsSdr25:
825         if ((CardSupportedBusTimings & BIT1) != 0) {
826           return TRUE;
827         }
828         break;
829       case SdMmcUhsSdr12:
830         if ((CardSupportedBusTimings & BIT0) != 0) {
831           return TRUE;
832         }
833         break;
834       default:
835         break;
836     }
837   } else {
838     switch (BusTiming) {
839       case SdMmcSdHs:
840         if ((Capability->HighSpeed != 0) && (CardSupportedBusTimings & BIT1) != 0) {
841           return TRUE;
842         }
843         break;
844       case SdMmcSdDs:
845         if ((CardSupportedBusTimings & BIT0) != 0) {
846           return TRUE;
847         }
848         break;
849       default:
850         break;
851     }
852   }
853 
854   return FALSE;
855 }
856 
857 /**
858   Get the target bus timing to set on the link. This function
859   will try to select highest bus timing supported by card, controller
860   and the driver.
861 
862   @param[in] Private                  Pointer to controller private data
863   @param[in] SlotIndex                Index of the slot in the controller
864   @param[in] CardSupportedBusTimings  Bitmask indicating which bus timings are supported by card
865   @param[in] IsInUhsI                 Flag indicating if link is in UHS-I
866 
867   @return  Bus timing value that should be set on link
868 **/
869 SD_MMC_BUS_MODE
SdGetTargetBusTiming(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN UINT8 CardSupportedBusTimings,IN BOOLEAN IsInUhsI)870 SdGetTargetBusTiming (
871   IN SD_MMC_HC_PRIVATE_DATA  *Private,
872   IN UINT8                   SlotIndex,
873   IN UINT8                   CardSupportedBusTimings,
874   IN BOOLEAN                 IsInUhsI
875   )
876 {
877   SD_MMC_BUS_MODE  BusTiming;
878 
879   if (IsInUhsI) {
880     BusTiming = SdMmcUhsSdr104;
881   } else {
882     BusTiming = SdMmcSdHs;
883   }
884 
885   while (BusTiming > SdMmcSdDs) {
886     if (SdIsBusTimingSupported (Private, SlotIndex, CardSupportedBusTimings, IsInUhsI, BusTiming)) {
887       break;
888     }
889     BusTiming--;
890   }
891 
892   return BusTiming;
893 }
894 
895 /**
896   Get the target bus width to be set on the bus.
897 
898   @param[in] Private    Pointer to controller private data
899   @param[in] SlotIndex  Index of the slot in the controller
900   @param[in] BusTiming  Bus timing set on the bus
901 
902   @return Bus width to be set on the bus
903 **/
904 UINT8
SdGetTargetBusWidth(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN SD_MMC_BUS_MODE BusTiming)905 SdGetTargetBusWidth (
906   IN SD_MMC_HC_PRIVATE_DATA   *Private,
907   IN UINT8                    SlotIndex,
908   IN SD_MMC_BUS_MODE          BusTiming
909   )
910 {
911   UINT8  BusWidth;
912   UINT8  PreferredBusWidth;
913 
914   PreferredBusWidth = Private->Slot[SlotIndex].OperatingParameters.BusWidth;
915 
916   if (BusTiming == SdMmcSdDs || BusTiming == SdMmcSdHs) {
917     if (PreferredBusWidth != EDKII_SD_MMC_BUS_WIDTH_IGNORE &&
918         (PreferredBusWidth == 1 || PreferredBusWidth == 4)) {
919       BusWidth = PreferredBusWidth;
920     } else {
921       BusWidth = 4;
922     }
923   } else {
924     //
925     // UHS-I modes support only 4-bit width.
926     // Switch to 4-bit has been done before calling this function anyway so
927     // this is purely informational.
928     //
929     BusWidth = 4;
930   }
931 
932   return BusWidth;
933 }
934 
935 /**
936   Get the target clock frequency to be set on the bus.
937 
938   @param[in] Private    Pointer to controller private data
939   @param[in] SlotIndex  Index of the slot in the controller
940   @param[in] BusTiming  Bus timing to be set on the bus
941 
942   @return Value of the clock frequency to be set on bus in MHz
943 **/
944 UINT32
SdGetTargetBusClockFreq(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN SD_MMC_BUS_MODE BusTiming)945 SdGetTargetBusClockFreq (
946   IN SD_MMC_HC_PRIVATE_DATA   *Private,
947   IN UINT8                    SlotIndex,
948   IN SD_MMC_BUS_MODE          BusTiming
949   )
950 {
951   UINT32 PreferredClockFreq;
952   UINT32 MaxClockFreq;
953 
954   PreferredClockFreq = Private->Slot[SlotIndex].OperatingParameters.ClockFreq;
955 
956   switch (BusTiming) {
957     case SdMmcUhsSdr104:
958       MaxClockFreq = 208;
959       break;
960     case SdMmcUhsSdr50:
961       MaxClockFreq = 100;
962       break;
963     case SdMmcUhsDdr50:
964     case SdMmcUhsSdr25:
965     case SdMmcSdHs:
966       MaxClockFreq = 50;
967       break;
968     case SdMmcUhsSdr12:
969     case SdMmcSdDs:
970     default:
971       MaxClockFreq = 25;
972   }
973 
974   if (PreferredClockFreq != EDKII_SD_MMC_CLOCK_FREQ_IGNORE && PreferredClockFreq < MaxClockFreq) {
975     return PreferredClockFreq;
976   } else {
977     return MaxClockFreq;
978   }
979 }
980 
981 /**
982   Get the driver strength to be set on bus.
983 
984   @param[in] Private                       Pointer to controller private data
985   @param[in] SlotIndex                     Index of the slot in the controller
986   @param[in] CardSupportedDriverStrengths  Bitmask indicating which driver strengths are supported on the card
987   @param[in] BusTiming                     Bus timing set on the bus
988 
989   @return Value of the driver strength to be set on the bus
990 **/
991 EDKII_SD_MMC_DRIVER_STRENGTH
SdGetTargetDriverStrength(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN UINT8 CardSupportedDriverStrengths,IN SD_MMC_BUS_MODE BusTiming)992 SdGetTargetDriverStrength (
993   IN SD_MMC_HC_PRIVATE_DATA   *Private,
994   IN UINT8                    SlotIndex,
995   IN UINT8                    CardSupportedDriverStrengths,
996   IN SD_MMC_BUS_MODE          BusTiming
997   )
998 {
999   EDKII_SD_MMC_DRIVER_STRENGTH  PreferredDriverStrength;
1000   EDKII_SD_MMC_DRIVER_STRENGTH  DriverStrength;
1001 
1002   if (BusTiming == SdMmcSdDs || BusTiming == SdMmcSdHs) {
1003     DriverStrength.Sd = SdDriverStrengthIgnore;
1004     return DriverStrength;
1005   }
1006 
1007   PreferredDriverStrength = Private->Slot[SlotIndex].OperatingParameters.DriverStrength;
1008   DriverStrength.Sd = SdDriverStrengthTypeB;
1009 
1010   if (PreferredDriverStrength.Sd != EDKII_SD_MMC_DRIVER_STRENGTH_IGNORE &&
1011       (CardSupportedDriverStrengths & (BIT0 << PreferredDriverStrength.Sd))) {
1012 
1013     if ((PreferredDriverStrength.Sd == SdDriverStrengthTypeA &&
1014         (Private->Capability[SlotIndex].DriverTypeA != 0)) ||
1015         (PreferredDriverStrength.Sd == SdDriverStrengthTypeC &&
1016         (Private->Capability[SlotIndex].DriverTypeC != 0)) ||
1017         (PreferredDriverStrength.Sd == SdDriverStrengthTypeD &&
1018         (Private->Capability[SlotIndex].DriverTypeD != 0))) {
1019       DriverStrength.Sd = PreferredDriverStrength.Sd;
1020     }
1021   }
1022 
1023   return DriverStrength;
1024 }
1025 
1026 /**
1027   Get the target settings for the bus mode.
1028 
1029   @param[in]  Private          Pointer to controller private data
1030   @param[in]  SlotIndex        Index of the slot in the controller
1031   @param[in]  SwitchQueryResp  Pointer to switch query response
1032   @param[in]  IsInUhsI         Flag indicating if link is in UHS-I mode
1033   @param[out] BusMode          Target configuration of the bus
1034 **/
1035 VOID
SdGetTargetBusMode(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 SlotIndex,IN UINT8 * SwitchQueryResp,IN BOOLEAN IsInUhsI,OUT SD_MMC_BUS_SETTINGS * BusMode)1036 SdGetTargetBusMode (
1037   IN SD_MMC_HC_PRIVATE_DATA  *Private,
1038   IN UINT8                   SlotIndex,
1039   IN UINT8                   *SwitchQueryResp,
1040   IN BOOLEAN                 IsInUhsI,
1041   OUT SD_MMC_BUS_SETTINGS    *BusMode
1042   )
1043 {
1044   BusMode->BusTiming = SdGetTargetBusTiming (Private, SlotIndex, SwitchQueryResp[13], IsInUhsI);
1045   BusMode->BusWidth = SdGetTargetBusWidth (Private, SlotIndex, BusMode->BusTiming);
1046   BusMode->ClockFreq = SdGetTargetBusClockFreq (Private, SlotIndex, BusMode->BusTiming);
1047   BusMode->DriverStrength = SdGetTargetDriverStrength (Private, SlotIndex, SwitchQueryResp[9], BusMode->BusTiming);
1048 }
1049 
1050 /**
1051   Switch the high speed timing according to request.
1052 
1053   Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 and
1054   SD Host Controller Simplified Spec 3.0 section Figure 2-29 for details.
1055 
1056   @param[in] PciIo          A pointer to the EFI_PCI_IO_PROTOCOL instance.
1057   @param[in] PassThru       A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
1058   @param[in] Slot           The slot number of the SD card to send the command to.
1059   @param[in] Rca            The relative device address to be assigned.
1060   @param[in] S18A           The boolean to show if it's a UHS-I SD card.
1061 
1062   @retval EFI_SUCCESS       The operation is done correctly.
1063   @retval Others            The operation fails.
1064 
1065 **/
1066 EFI_STATUS
SdCardSetBusMode(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_SD_MMC_PASS_THRU_PROTOCOL * PassThru,IN UINT8 Slot,IN UINT16 Rca,IN BOOLEAN S18A)1067 SdCardSetBusMode (
1068   IN EFI_PCI_IO_PROTOCOL                *PciIo,
1069   IN EFI_SD_MMC_PASS_THRU_PROTOCOL      *PassThru,
1070   IN UINT8                              Slot,
1071   IN UINT16                             Rca,
1072   IN BOOLEAN                            S18A
1073   )
1074 {
1075   EFI_STATUS                   Status;
1076   SD_MMC_HC_SLOT_CAP           *Capability;
1077   UINT8                        HostCtrl1;
1078   UINT8                        SwitchResp[64];
1079   SD_MMC_HC_PRIVATE_DATA       *Private;
1080   SD_MMC_BUS_SETTINGS          BusMode;
1081 
1082   Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
1083 
1084   Capability = &Private->Capability[Slot];
1085 
1086   Status = SdCardSelect (PassThru, Slot, Rca);
1087   if (EFI_ERROR (Status)) {
1088     return Status;
1089   }
1090 
1091   if (S18A) {
1092     //
1093     // For UHS-I speed modes 4-bit data bus is requiered so we
1094     // switch here irrespective of platform preference.
1095     //
1096     Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, 4);
1097     if (EFI_ERROR (Status)) {
1098       return Status;
1099     }
1100   }
1101 
1102   //
1103   // Get the supported bus speed from SWITCH cmd return data group #1.
1104   //
1105   Status = SdCardSwitch (PassThru, Slot, 0xFF, 0xF, SdDriverStrengthIgnore, 0xF, FALSE, SwitchResp);
1106   if (EFI_ERROR (Status)) {
1107     return Status;
1108   }
1109 
1110   SdGetTargetBusMode (Private, Slot, SwitchResp, S18A, &BusMode);
1111 
1112   DEBUG ((DEBUG_INFO, "SdCardSetBusMode: Target bus mode: bus timing = %d, bus width = %d, clock freq[MHz] = %d, driver strength = %d\n",
1113                          BusMode.BusTiming, BusMode.BusWidth, BusMode.ClockFreq, BusMode.DriverStrength.Sd));
1114 
1115   if (!S18A) {
1116     Status = SdCardSwitchBusWidth (PciIo, PassThru, Slot, Rca, BusMode.BusWidth);
1117     if (EFI_ERROR (Status)) {
1118       return Status;
1119     }
1120   }
1121 
1122   Status = SdCardSwitch (PassThru, Slot, BusMode.BusTiming, 0xF, BusMode.DriverStrength.Sd, 0xF, TRUE, SwitchResp);
1123   if (EFI_ERROR (Status)) {
1124     return Status;
1125   }
1126 
1127   Status = SdMmcSetDriverStrength (Private->PciIo, Slot, BusMode.DriverStrength.Sd);
1128   if (EFI_ERROR (Status)) {
1129     return Status;
1130   }
1131 
1132   //
1133   // Set to High Speed timing
1134   //
1135   if (BusMode.BusTiming == SdMmcSdHs) {
1136     HostCtrl1 = BIT2;
1137     Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL1, sizeof (HostCtrl1), &HostCtrl1);
1138     if (EFI_ERROR (Status)) {
1139       return Status;
1140     }
1141   }
1142 
1143   Status = SdMmcHcUhsSignaling (Private->ControllerHandle, PciIo, Slot, BusMode.BusTiming);
1144   if (EFI_ERROR (Status)) {
1145     return Status;
1146   }
1147 
1148   Status = SdMmcHcClockSupply (PciIo, Slot, BusMode.ClockFreq * 1000, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
1149   if (EFI_ERROR (Status)) {
1150     return Status;
1151   }
1152 
1153   if (mOverride != NULL && mOverride->NotifyPhase != NULL) {
1154     Status = mOverride->NotifyPhase (
1155                           Private->ControllerHandle,
1156                           Slot,
1157                           EdkiiSdMmcSwitchClockFreqPost,
1158                           &BusMode.BusTiming
1159                           );
1160     if (EFI_ERROR (Status)) {
1161       DEBUG ((
1162         DEBUG_ERROR,
1163         "%a: SD/MMC switch clock freq post notifier callback failed - %r\n",
1164         __FUNCTION__,
1165         Status
1166         ));
1167       return Status;
1168     }
1169   }
1170 
1171   if ((BusMode.BusTiming == SdMmcUhsSdr104) || ((BusMode.BusTiming == SdMmcUhsSdr50) && (Capability->TuningSDR50 != 0))) {
1172     Status = SdCardTuningClock (PciIo, PassThru, Slot);
1173     if (EFI_ERROR (Status)) {
1174       return Status;
1175     }
1176   }
1177 
1178   return Status;
1179 }
1180 
1181 /**
1182   Execute SD device identification procedure.
1183 
1184   Refer to SD Physical Layer Simplified Spec 4.1 Section 3.6 for details.
1185 
1186   @param[in] Private        A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
1187   @param[in] Slot           The slot number of the SD card to send the command to.
1188 
1189   @retval EFI_SUCCESS       There is a SD card.
1190   @retval Others            There is not a SD card.
1191 
1192 **/
1193 EFI_STATUS
SdCardIdentification(IN SD_MMC_HC_PRIVATE_DATA * Private,IN UINT8 Slot)1194 SdCardIdentification (
1195   IN SD_MMC_HC_PRIVATE_DATA             *Private,
1196   IN UINT8                              Slot
1197   )
1198 {
1199   EFI_STATUS                     Status;
1200   EFI_PCI_IO_PROTOCOL            *PciIo;
1201   EFI_SD_MMC_PASS_THRU_PROTOCOL  *PassThru;
1202   UINT32                         Ocr;
1203   UINT16                         Rca;
1204   BOOLEAN                        Xpc;
1205   BOOLEAN                        S18r;
1206   UINT64                         MaxCurrent;
1207   UINT16                         ControllerVer;
1208   UINT8                          PowerCtrl;
1209   UINT32                         PresentState;
1210   UINT8                          HostCtrl2;
1211   UINTN                          Retry;
1212 
1213   PciIo    = Private->PciIo;
1214   PassThru = &Private->PassThru;
1215   //
1216   // 1. Send Cmd0 to the device
1217   //
1218   Status = SdCardReset (PassThru, Slot);
1219   if (EFI_ERROR (Status)) {
1220     DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd0 fails with %r\n", Status));
1221     return Status;
1222   }
1223   //
1224   // 2. Send Cmd8 to the device
1225   //
1226   Status = SdCardVoltageCheck (PassThru, Slot, 0x1, 0xFF);
1227   if (EFI_ERROR (Status)) {
1228     DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing Cmd8 fails with %r\n", Status));
1229     return Status;
1230   }
1231   //
1232   // 3. Send SDIO Cmd5 to the device to the SDIO device OCR register.
1233   //
1234   Status = SdioSendOpCond (PassThru, Slot, 0, FALSE);
1235   if (!EFI_ERROR (Status)) {
1236     DEBUG ((DEBUG_INFO, "SdCardIdentification: Found SDIO device, ignore it as we don't support\n"));
1237     return EFI_DEVICE_ERROR;
1238   }
1239   //
1240   // 4. Send Acmd41 with voltage window 0 to the device
1241   //
1242   Status = SdCardSendOpCond (PassThru, Slot, 0, 0, FALSE, FALSE, FALSE, &Ocr);
1243   if (EFI_ERROR (Status)) {
1244     DEBUG ((DEBUG_INFO, "SdCardIdentification: Executing SdCardSendOpCond fails with %r\n", Status));
1245     return EFI_DEVICE_ERROR;
1246   }
1247 
1248   if (Private->Capability[Slot].Voltage33 != 0) {
1249     //
1250     // Support 3.3V
1251     //
1252     MaxCurrent = ((UINT32)Private->MaxCurrent[Slot] & 0xFF) * 4;
1253   } else if (Private->Capability[Slot].Voltage30 != 0) {
1254     //
1255     // Support 3.0V
1256     //
1257     MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 8) & 0xFF) * 4;
1258   } else if (Private->Capability[Slot].Voltage18 != 0) {
1259     //
1260     // Support 1.8V
1261     //
1262     MaxCurrent = (((UINT32)Private->MaxCurrent[Slot] >> 16) & 0xFF) * 4;
1263   } else {
1264     ASSERT (FALSE);
1265     return EFI_DEVICE_ERROR;
1266   }
1267 
1268   if (MaxCurrent >= 150) {
1269     Xpc = TRUE;
1270   } else {
1271     Xpc = FALSE;
1272   }
1273 
1274   Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CTRL_VER, TRUE, sizeof (ControllerVer), &ControllerVer);
1275   if (EFI_ERROR (Status)) {
1276     return Status;
1277   }
1278 
1279   if (((ControllerVer & 0xFF) >= SD_MMC_HC_CTRL_VER_300) &&
1280       ((ControllerVer & 0xFF) <= SD_MMC_HC_CTRL_VER_420)) {
1281     S18r = TRUE;
1282   } else if (((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_100) || ((ControllerVer & 0xFF) == SD_MMC_HC_CTRL_VER_200)) {
1283     S18r = FALSE;
1284   } else {
1285     ASSERT (FALSE);
1286     return EFI_UNSUPPORTED;
1287   }
1288   //
1289   // 5. Repeatly send Acmd41 with supply voltage window to the device.
1290   //    Note here we only support the cards complied with SD physical
1291   //    layer simplified spec version 2.0 and version 3.0 and above.
1292   //
1293   Ocr   = 0;
1294   Retry = 0;
1295   do {
1296     Status = SdCardSendOpCond (PassThru, Slot, 0, Ocr, S18r, Xpc, TRUE, &Ocr);
1297     if (EFI_ERROR (Status)) {
1298       DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails with %r Ocr %x, S18r %x, Xpc %x\n", Status, Ocr, S18r, Xpc));
1299       return EFI_DEVICE_ERROR;
1300     }
1301 
1302     if (Retry++ == 100) {
1303       DEBUG ((DEBUG_ERROR, "SdCardIdentification: SdCardSendOpCond fails too many times\n"));
1304       return EFI_DEVICE_ERROR;
1305     }
1306     gBS->Stall(10 * 1000);
1307   } while ((Ocr & BIT31) == 0);
1308 
1309   //
1310   // 6. If the S18A bit is set and the Host Controller supports 1.8V signaling
1311   //    (One of support bits is set to 1: SDR50, SDR104 or DDR50 in the
1312   //    Capabilities register), switch its voltage to 1.8V.
1313   //
1314   if ((Private->Capability[Slot].Sdr50 != 0 ||
1315        Private->Capability[Slot].Sdr104 != 0 ||
1316        Private->Capability[Slot].Ddr50 != 0) &&
1317        ((Ocr & BIT24) != 0)) {
1318     Status = SdCardVoltageSwitch (PassThru, Slot);
1319     if (EFI_ERROR (Status)) {
1320       DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardVoltageSwitch fails with %r\n", Status));
1321       Status = EFI_DEVICE_ERROR;
1322       goto Error;
1323     } else {
1324       Status = SdMmcHcStopClock (PciIo, Slot);
1325       if (EFI_ERROR (Status)) {
1326         Status = EFI_DEVICE_ERROR;
1327         goto Error;
1328       }
1329 
1330       SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
1331       if (((PresentState >> 20) & 0xF) != 0) {
1332         DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x\n", PresentState));
1333         Status = EFI_DEVICE_ERROR;
1334         goto Error;
1335       }
1336       HostCtrl2  = BIT3;
1337       SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
1338 
1339       gBS->Stall (5000);
1340 
1341       SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
1342       if ((HostCtrl2 & BIT3) == 0) {
1343         DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with HostCtrl2 = 0x%x\n", HostCtrl2));
1344         Status = EFI_DEVICE_ERROR;
1345         goto Error;
1346       }
1347 
1348       SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot], Private->ControllerVersion[Slot]);
1349 
1350       gBS->Stall (1000);
1351 
1352       SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof (PresentState), &PresentState);
1353       if (((PresentState >> 20) & 0xF) != 0xF) {
1354         DEBUG ((DEBUG_ERROR, "SdCardIdentification: SwitchVoltage fails with PresentState = 0x%x, It should be 0xF\n", PresentState));
1355         Status = EFI_DEVICE_ERROR;
1356         goto Error;
1357       }
1358     }
1359     DEBUG ((DEBUG_INFO, "SdCardIdentification: Switch to 1.8v signal voltage success\n"));
1360   }
1361 
1362   Status = SdCardAllSendCid (PassThru, Slot);
1363   if (EFI_ERROR (Status)) {
1364     DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardAllSendCid fails with %r\n", Status));
1365     return Status;
1366   }
1367 
1368   Status = SdCardSetRca (PassThru, Slot, &Rca);
1369   if (EFI_ERROR (Status)) {
1370     DEBUG ((DEBUG_ERROR, "SdCardIdentification: Executing SdCardSetRca fails with %r\n", Status));
1371     return Status;
1372   }
1373   //
1374   // Enter Data Tranfer Mode.
1375   //
1376   DEBUG ((DEBUG_INFO, "SdCardIdentification: Found a SD device at slot [%d]\n", Slot));
1377   Private->Slot[Slot].CardType = SdCardType;
1378 
1379   Status = SdCardSetBusMode (PciIo, PassThru, Slot, Rca, ((Ocr & BIT24) != 0));
1380 
1381   return Status;
1382 
1383 Error:
1384   //
1385   // Set SD Bus Power = 0
1386   //
1387   PowerCtrl = (UINT8)~BIT0;
1388   Status = SdMmcHcAndMmio (PciIo, Slot, SD_MMC_HC_POWER_CTRL, sizeof (PowerCtrl), &PowerCtrl);
1389   return EFI_DEVICE_ERROR;
1390 }
1391 
1392