]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
ArmPlatformPkg/PL011Uart: PL011UartWrite() stop to transmit if the buffer is full
[mirror_edk2.git] / ArmPlatformPkg / Drivers / PL180MciDxe / PL180Mci.c
CommitLineData
633724f4 1/** @file\r
2 This file implement the MMC Host Protocol for the ARM PrimeCell PL180.\r
3\r
93b429fc 4 Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
633724f4 5 \r
6 This program and the accompanying materials \r
7 are licensed and made available under the terms and conditions of the BSD License \r
8 which accompanies this distribution. The full text of the license may be found at \r
9 http://opensource.org/licenses/bsd-license.php \r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
14**/\r
15\r
16#include "PL180Mci.h"\r
17\r
18#include <Library/DevicePathLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20\r
21EFI_MMC_HOST_PROTOCOL *gpMmcHost;\r
22\r
23// Untested ...\r
24//#define USE_STREAM\r
25\r
26#define MMCI0_BLOCKLEN 512\r
27#define MMCI0_POW2_BLOCKLEN 9\r
28#define MMCI0_TIMEOUT 1000\r
29\r
93b429fc 30#define SYS_MCI_CARDIN BIT0\r
31#define SYS_MCI_WPROT BIT1\r
32\r
633724f4 33BOOLEAN\r
34MciIsPowerOn (\r
35 VOID\r
36 )\r
37{\r
93b429fc 38 return ((MmioRead32 (MCI_POWER_CONTROL_REG) & MCI_POWER_ON) == MCI_POWER_ON);\r
633724f4 39}\r
40\r
41EFI_STATUS\r
42MciInitialize (\r
43 VOID\r
44 )\r
45{\r
93b429fc 46 MCI_TRACE ("MciInitialize()");\r
633724f4 47 return EFI_SUCCESS;\r
48}\r
49\r
50BOOLEAN\r
51MciIsCardPresent (\r
16d88c2d 52 IN EFI_MMC_HOST_PROTOCOL *This\r
633724f4 53 )\r
54{\r
93b429fc 55 return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_CARDIN);\r
633724f4 56}\r
57\r
58BOOLEAN\r
59MciIsReadOnly (\r
16d88c2d 60 IN EFI_MMC_HOST_PROTOCOL *This\r
633724f4 61 )\r
62{\r
93b429fc 63 return (MmioRead32 (FixedPcdGet32 (PcdPL180SysMciRegAddress)) & SYS_MCI_WPROT);\r
633724f4 64}\r
65\r
66#if 0\r
67//Note: This function has been commented out because it is not used yet.\r
68// This function could be used to remove the hardcoded BlockLen used\r
69// in MciPrepareDataPath\r
70\r
71// Convert block size to 2^n\r
72STATIC\r
73UINT32\r
74GetPow2BlockLen (\r
75 IN UINT32 BlockLen\r
76 )\r
77{\r
78 UINTN Loop;\r
79 UINTN Pow2BlockLen;\r
80\r
81 Loop = 0x8000;\r
82 Pow2BlockLen = 15;\r
83 do {\r
84 Loop = (Loop >> 1) & 0xFFFF;\r
85 Pow2BlockLen--;\r
86 } while (Pow2BlockLen && (!(Loop & BlockLen)));\r
87\r
88 return Pow2BlockLen;\r
89}\r
90#endif\r
91\r
92VOID\r
93MciPrepareDataPath (\r
94 IN UINTN TransferDirection\r
95 )\r
96{\r
97 // Set Data Length & Data Timer\r
93b429fc 98 MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFFFF);\r
99 MmioWrite32 (MCI_DATA_LENGTH_REG, MMCI0_BLOCKLEN);\r
633724f4 100\r
101#ifndef USE_STREAM\r
93b429fc 102 //Note: we are using a hardcoded BlockLen (==512). If we decide to use a variable size, we could\r
103 // compute the pow2 of BlockLen with the above function GetPow2BlockLen ()\r
104 MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | (MMCI0_POW2_BLOCKLEN << 4));\r
633724f4 105#else\r
16d88c2d 106 MmioWrite32 (MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | MCI_DATACTL_STREAM_TRANS);\r
633724f4 107#endif\r
108}\r
109\r
110EFI_STATUS\r
111MciSendCommand (\r
16d88c2d 112 IN EFI_MMC_HOST_PROTOCOL *This,\r
113 IN MMC_CMD MmcCmd,\r
114 IN UINT32 Argument\r
633724f4 115 )\r
116{\r
93b429fc 117 UINT32 Status;\r
118 UINT32 Cmd;\r
119 UINTN RetVal;\r
120 UINTN CmdCtrlReg;\r
633724f4 121\r
122 RetVal = EFI_SUCCESS;\r
123\r
124 if ((MmcCmd == MMC_CMD17) || (MmcCmd == MMC_CMD11)) {\r
93b429fc 125 MciPrepareDataPath (MCI_DATACTL_CARD_TO_CONT);\r
633724f4 126 } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {\r
93b429fc 127 MciPrepareDataPath (MCI_DATACTL_CONT_TO_CARD);\r
633724f4 128 }\r
129\r
130 // Create Command for PL180\r
93b429fc 131 Cmd = (MMC_GET_INDX (MmcCmd) & INDX_MASK) | MCI_CPSM_ENABLE;\r
633724f4 132 if (MmcCmd & MMC_CMD_WAIT_RESPONSE) {\r
133 Cmd |= MCI_CPSM_WAIT_RESPONSE;\r
134 }\r
135\r
136 if (MmcCmd & MMC_CMD_LONG_RESPONSE) {\r
137 Cmd |= MCI_CPSM_LONG_RESPONSE;\r
138 }\r
139\r
140 // Clear Status register static flags\r
93b429fc 141 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
633724f4 142\r
93b429fc 143 // Write to command argument register\r
144 MmioWrite32 (MCI_ARGUMENT_REG, Argument);\r
633724f4 145\r
93b429fc 146 // Write to command register\r
147 MmioWrite32 (MCI_COMMAND_REG, Cmd);\r
633724f4 148\r
149 if (Cmd & MCI_CPSM_WAIT_RESPONSE) {\r
93b429fc 150 Status = MmioRead32 (MCI_STATUS_REG);\r
633724f4 151 while (!(Status & (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT | MCI_STATUS_CMD_START_BIT_ERROR))) {\r
152 Status = MmioRead32(MCI_STATUS_REG);\r
153 }\r
154\r
155 if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {\r
93b429fc 156 DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 157 RetVal = EFI_NO_RESPONSE;\r
158 goto Exit;\r
159 } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {\r
93b429fc 160 //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 161 RetVal = EFI_TIMEOUT;\r
162 goto Exit;\r
93b429fc 163 } else if ((! (MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
633724f4 164 // The CMD1 and response type R3 do not contain CRC. We should ignore the CRC failed Status.\r
165 RetVal = EFI_CRC_ERROR;\r
166 goto Exit;\r
167 } else {\r
168 RetVal = EFI_SUCCESS;\r
169 goto Exit;\r
170 }\r
171 } else {\r
172 Status = MmioRead32(MCI_STATUS_REG);\r
173 while (!(Status & (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT| MCI_STATUS_CMD_START_BIT_ERROR))) {\r
174 Status = MmioRead32(MCI_STATUS_REG);\r
175 }\r
176\r
177 if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {\r
178 DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));\r
179 RetVal = EFI_NO_RESPONSE;\r
180 goto Exit;\r
181 } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {\r
182 //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));\r
183 RetVal = EFI_TIMEOUT;\r
184 goto Exit;\r
185 } else\r
186 if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
187 // The CMD1 does not contain CRC. We should ignore the CRC failed Status.\r
188 RetVal = EFI_CRC_ERROR;\r
189 goto Exit;\r
190 } else {\r
191 RetVal = EFI_SUCCESS;\r
192 goto Exit;\r
193 }\r
194 }\r
195\r
196Exit:\r
93b429fc 197 // Disable Command Path\r
198 CmdCtrlReg = MmioRead32 (MCI_COMMAND_REG);\r
199 MmioWrite32 (MCI_COMMAND_REG, (CmdCtrlReg & ~MCI_CPSM_ENABLE));\r
200 return RetVal;\r
633724f4 201}\r
202\r
203EFI_STATUS\r
204MciReceiveResponse (\r
16d88c2d 205 IN EFI_MMC_HOST_PROTOCOL *This,\r
206 IN MMC_RESPONSE_TYPE Type,\r
207 IN UINT32* Buffer\r
633724f4 208 )\r
209{\r
210 if (Buffer == NULL) {\r
211 return EFI_INVALID_PARAMETER;\r
212 }\r
213\r
93b429fc 214 if ( (Type == MMC_RESPONSE_TYPE_R1)\r
215 || (Type == MMC_RESPONSE_TYPE_R1b)\r
216 || (Type == MMC_RESPONSE_TYPE_R3)\r
217 || (Type == MMC_RESPONSE_TYPE_R6)\r
218 || (Type == MMC_RESPONSE_TYPE_R7))\r
633724f4 219 {\r
93b429fc 220 Buffer[0] = MmioRead32 (MCI_RESPONSE3_REG);\r
633724f4 221 } else if (Type == MMC_RESPONSE_TYPE_R2) {\r
93b429fc 222 Buffer[0] = MmioRead32 (MCI_RESPONSE0_REG);\r
223 Buffer[1] = MmioRead32 (MCI_RESPONSE1_REG);\r
224 Buffer[2] = MmioRead32 (MCI_RESPONSE2_REG);\r
225 Buffer[3] = MmioRead32 (MCI_RESPONSE3_REG);\r
633724f4 226 }\r
227\r
228 return EFI_SUCCESS;\r
229}\r
230\r
231EFI_STATUS\r
232MciReadBlockData (\r
16d88c2d 233 IN EFI_MMC_HOST_PROTOCOL *This,\r
234 IN EFI_LBA Lba,\r
235 IN UINTN Length,\r
236 IN UINT32* Buffer\r
633724f4 237 )\r
238{\r
239 UINTN Loop;\r
240 UINTN Finish;\r
241 UINTN Status;\r
242 EFI_STATUS RetVal;\r
243 UINTN DataCtrlReg;\r
244\r
245 RetVal = EFI_SUCCESS;\r
246\r
247 // Read data from the RX FIFO\r
248 Loop = 0;\r
249 Finish = MMCI0_BLOCKLEN / 4;\r
250 do {\r
251 // Read the Status flags\r
93b429fc 252 Status = MmioRead32 (MCI_STATUS_REG);\r
633724f4 253\r
254 // Do eight reads if possible else a single read\r
255 if (Status & MCI_STATUS_CMD_RXFIFOHALFFULL) {\r
256 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
257 Loop++;\r
258 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
259 Loop++;\r
260 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
261 Loop++;\r
262 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
263 Loop++;\r
264 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
265 Loop++;\r
266 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
267 Loop++;\r
268 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
269 Loop++;\r
270 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
271 Loop++;\r
272 } else if (Status & MCI_STATUS_CMD_RXDATAAVAILBL) {\r
273 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
274 Loop++;\r
275 } else {\r
276 //Check for error conditions and timeouts\r
93b429fc 277 if (Status & MCI_STATUS_CMD_DATATIMEOUT) {\r
278 DEBUG ((EFI_D_ERROR, "MciReadBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 279 RetVal = EFI_TIMEOUT;\r
280 break;\r
93b429fc 281 } else if (Status & MCI_STATUS_CMD_DATACRCFAIL) {\r
282 DEBUG ((EFI_D_ERROR, "MciReadBlockData(): CRC Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 283 RetVal = EFI_CRC_ERROR;\r
284 break;\r
93b429fc 285 } else if (Status & MCI_STATUS_CMD_START_BIT_ERROR) {\r
286 DEBUG ((EFI_D_ERROR, "MciReadBlockData(): Start-bit Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 287 RetVal = EFI_NO_RESPONSE;\r
288 break;\r
289 }\r
290 }\r
291 //clear RX over run flag\r
292 if(Status & MCI_STATUS_CMD_RXOVERRUN) {\r
293 MmioWrite32(MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_RXOVERRUN);\r
294 }\r
295 } while ((Loop < Finish));\r
296\r
93b429fc 297 // Clear Status flags\r
298 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
633724f4 299\r
93b429fc 300 //Disable Data path\r
301 DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);\r
302 MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));\r
633724f4 303\r
93b429fc 304 return RetVal;\r
633724f4 305}\r
306\r
307EFI_STATUS\r
308MciWriteBlockData (\r
16d88c2d 309 IN EFI_MMC_HOST_PROTOCOL *This,\r
310 IN EFI_LBA Lba,\r
311 IN UINTN Length,\r
312 IN UINT32* Buffer\r
633724f4 313 )\r
314{\r
315 UINTN Loop;\r
316 UINTN Finish;\r
317 UINTN Timer;\r
318 UINTN Status;\r
319 EFI_STATUS RetVal;\r
320 UINTN DataCtrlReg;\r
321\r
322 RetVal = EFI_SUCCESS;\r
323\r
324 // Write the data to the TX FIFO\r
325 Loop = 0;\r
326 Finish = MMCI0_BLOCKLEN / 4;\r
327 Timer = MMCI0_TIMEOUT * 100;\r
328 do {\r
329 // Read the Status flags\r
93b429fc 330 Status = MmioRead32 (MCI_STATUS_REG);\r
633724f4 331\r
332 // Do eight writes if possible else a single write\r
333 if (Status & MCI_STATUS_CMD_TXFIFOHALFEMPTY) {\r
334 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
335 Loop++;\r
336 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
337 Loop++;\r
338 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
339 Loop++;\r
340 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
341 Loop++;\r
342 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
343 Loop++;\r
344 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
345 Loop++;\r
346 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
347 Loop++;\r
348 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
349 Loop++;\r
350 } else if ((Status & MCI_STATUS_CMD_TXFIFOEMPTY)) {\r
351 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
352 Loop++;\r
353 } else {\r
93b429fc 354 // Check for error conditions and timeouts\r
355 if (Status & MCI_STATUS_CMD_DATATIMEOUT) {\r
356 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 357 RetVal = EFI_TIMEOUT;\r
358 goto Exit;\r
93b429fc 359 } else if (Status & MCI_STATUS_CMD_DATACRCFAIL) {\r
360 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): CRC Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 361 RetVal = EFI_CRC_ERROR;\r
362 goto Exit;\r
93b429fc 363 } else if (Status & MCI_STATUS_CMD_TX_UNDERRUN) {\r
633724f4 364 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TX buffer Underrun! Response:0x%X Status:0x%x, Number of bytes written 0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status, Loop));\r
365 RetVal = EFI_BUFFER_TOO_SMALL;\r
366 ASSERT(0);\r
367 goto Exit;\r
368 }\r
369 }\r
370 } while (Loop < Finish);\r
371\r
372 // Wait for FIFO to drain\r
93b429fc 373 Timer = MMCI0_TIMEOUT * 60;\r
374 Status = MmioRead32 (MCI_STATUS_REG);\r
633724f4 375#ifndef USE_STREAM\r
376 // Single block\r
93b429fc 377 while (((Status & MCI_STATUS_TXDONE) != MCI_STATUS_TXDONE) && Timer) {\r
633724f4 378#else\r
379 // Stream\r
380 while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {\r
381#endif\r
382 NanoSecondDelay(10);\r
93b429fc 383 Status = MmioRead32 (MCI_STATUS_REG);\r
633724f4 384 Timer--;\r
385 }\r
386\r
93b429fc 387 if (Timer == 0) {\r
633724f4 388 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of bytes written 0x%x\n",Loop));\r
93b429fc 389 ASSERT (Timer > 0);\r
633724f4 390 return EFI_TIMEOUT;\r
391 }\r
392\r
93b429fc 393 // Clear Status flags\r
394 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
633724f4 395 if (Timer == 0) {\r
396 RetVal = EFI_TIMEOUT;\r
397 }\r
398\r
399Exit:\r
93b429fc 400 // Disable Data path\r
401 DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);\r
402 MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));\r
403 return RetVal;\r
633724f4 404}\r
405\r
406EFI_STATUS\r
407MciNotifyState (\r
16d88c2d 408 IN EFI_MMC_HOST_PROTOCOL *This,\r
409 IN MMC_STATE State\r
633724f4 410 )\r
411{\r
412 UINT32 Data32;\r
413\r
93b429fc 414 switch (State) {\r
633724f4 415 case MmcInvalidState:\r
93b429fc 416 ASSERT (0);\r
633724f4 417 break;\r
418 case MmcHwInitializationState:\r
419 // If device already turn on then restart it\r
93b429fc 420 Data32 = MmioRead32 (MCI_POWER_CONTROL_REG);\r
633724f4 421 if ((Data32 & 0x2) == MCI_POWER_UP) {\r
93b429fc 422 MCI_TRACE ("MciNotifyState(MmcHwInitializationState): TurnOff MCI");\r
633724f4 423\r
424 // Turn off\r
93b429fc 425 MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0);\r
426 MmioWrite32 (MCI_POWER_CONTROL_REG, 0);\r
427 MicroSecondDelay (100);\r
633724f4 428 }\r
429\r
93b429fc 430 MCI_TRACE ("MciNotifyState(MmcHwInitializationState): TurnOn MCI");\r
633724f4 431 // Setup clock\r
432 // - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz\r
93b429fc 433 MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);\r
633724f4 434 //MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE);\r
435\r
436 // Set the voltage\r
93b429fc 437 MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_OPENDRAIN | (15<<2));\r
438 MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_UP);\r
439 MicroSecondDelay (10);\r
440 MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_ON);\r
441 MicroSecondDelay (100);\r
633724f4 442\r
443 // Set Data Length & Data Timer\r
93b429fc 444 MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFF);\r
445 MmioWrite32 (MCI_DATA_LENGTH_REG, 8);\r
633724f4 446\r
93b429fc 447 ASSERT ((MmioRead32 (MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);\r
633724f4 448 break;\r
449 case MmcIdleState:\r
93b429fc 450 MCI_TRACE ("MciNotifyState(MmcIdleState)");\r
633724f4 451 break;\r
452 case MmcReadyState:\r
93b429fc 453 MCI_TRACE ("MciNotifyState(MmcReadyState)");\r
633724f4 454 break;\r
455 case MmcIdentificationState:\r
93b429fc 456 MCI_TRACE ("MciNotifyState (MmcIdentificationState)");\r
633724f4 457 break;\r
458 case MmcStandByState:{\r
459 volatile UINT32 PwrCtrlReg;\r
93b429fc 460 MCI_TRACE ("MciNotifyState (MmcStandByState)");\r
633724f4 461\r
462 // Enable MCICMD push-pull drive\r
93b429fc 463 PwrCtrlReg = MmioRead32 (MCI_POWER_CONTROL_REG);\r
633724f4 464 //Disable Open Drain output\r
93b429fc 465 PwrCtrlReg &= ~ (MCI_POWER_OPENDRAIN);\r
466 MmioWrite32 (MCI_POWER_CONTROL_REG, PwrCtrlReg);\r
633724f4 467\r
468 // Set MMCI0 clock to 4MHz (24MHz may be possible with cache enabled)\r
469 //\r
470 // Note: Increasing clock speed causes TX FIFO under-run errors.\r
471 // So careful when optimising this driver for higher performance.\r
472 //\r
473 MmioWrite32(MCI_CLOCK_CONTROL_REG,0x02 | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);\r
474 // Set MMCI0 clock to 24MHz (by bypassing the divider)\r
475 //MmioWrite32(MCI_CLOCK_CONTROL_REG,MCI_CLOCK_BYPASS | MCI_CLOCK_ENABLE);\r
476 break;\r
477 }\r
478 case MmcTransferState:\r
93b429fc 479 //MCI_TRACE ("MciNotifyState(MmcTransferState)");\r
633724f4 480 break;\r
481 case MmcSendingDataState:\r
93b429fc 482 MCI_TRACE ("MciNotifyState(MmcSendingDataState)");\r
633724f4 483 break;\r
484 case MmcReceiveDataState:\r
93b429fc 485 MCI_TRACE ("MciNotifyState(MmcReceiveDataState)");\r
633724f4 486 break;\r
487 case MmcProgrammingState:\r
93b429fc 488 MCI_TRACE ("MciNotifyState(MmcProgrammingState)");\r
633724f4 489 break;\r
490 case MmcDisconnectState:\r
93b429fc 491 MCI_TRACE ("MciNotifyState(MmcDisconnectState)");\r
633724f4 492 break;\r
493 default:\r
93b429fc 494 ASSERT (0);\r
633724f4 495 }\r
496 return EFI_SUCCESS;\r
497}\r
498\r
499EFI_GUID mPL180MciDevicePathGuid = EFI_CALLER_ID_GUID;\r
500\r
501EFI_STATUS\r
502MciBuildDevicePath (\r
16d88c2d 503 IN EFI_MMC_HOST_PROTOCOL *This,\r
504 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
633724f4 505 )\r
506{\r
507 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
508\r
93b429fc 509 NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));\r
510 CopyGuid (& ((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &mPL180MciDevicePathGuid);\r
633724f4 511\r
512 *DevicePath = NewDevicePathNode;\r
513 return EFI_SUCCESS;\r
514}\r
515\r
516EFI_MMC_HOST_PROTOCOL gMciHost = {\r
16d88c2d 517 MMC_HOST_PROTOCOL_REVISION,\r
633724f4 518 MciIsCardPresent,\r
519 MciIsReadOnly,\r
520 MciBuildDevicePath,\r
521 MciNotifyState,\r
522 MciSendCommand,\r
523 MciReceiveResponse,\r
524 MciReadBlockData,\r
525 MciWriteBlockData\r
526};\r
527\r
528EFI_STATUS\r
529PL180MciDxeInitialize (\r
530 IN EFI_HANDLE ImageHandle,\r
531 IN EFI_SYSTEM_TABLE *SystemTable\r
532 )\r
533{\r
534 EFI_STATUS Status;\r
93b429fc 535 EFI_HANDLE Handle;\r
536\r
537 Handle = NULL;\r
633724f4 538\r
93b429fc 539 MCI_TRACE ("PL180MciDxeInitialize()");\r
633724f4 540\r
541 //Publish Component Name, BlockIO protocol interfaces\r
542 Status = gBS->InstallMultipleProtocolInterfaces (\r
543 &Handle, \r
544 &gEfiMmcHostProtocolGuid, &gMciHost,\r
545 NULL\r
546 );\r
547 ASSERT_EFI_ERROR (Status);\r
548\r
549 return EFI_SUCCESS;\r
550}\r