]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
ARM Packages: Removed trailing spaces
[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
3402aac7
RC
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
633724f4 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
dad28de1 121 UINT32 DoneMask;\r
633724f4 122\r
123 RetVal = EFI_SUCCESS;\r
124\r
125 if ((MmcCmd == MMC_CMD17) || (MmcCmd == MMC_CMD11)) {\r
93b429fc 126 MciPrepareDataPath (MCI_DATACTL_CARD_TO_CONT);\r
633724f4 127 } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {\r
93b429fc 128 MciPrepareDataPath (MCI_DATACTL_CONT_TO_CARD);\r
633724f4 129 }\r
130\r
131 // Create Command for PL180\r
93b429fc 132 Cmd = (MMC_GET_INDX (MmcCmd) & INDX_MASK) | MCI_CPSM_ENABLE;\r
633724f4 133 if (MmcCmd & MMC_CMD_WAIT_RESPONSE) {\r
134 Cmd |= MCI_CPSM_WAIT_RESPONSE;\r
135 }\r
136\r
137 if (MmcCmd & MMC_CMD_LONG_RESPONSE) {\r
138 Cmd |= MCI_CPSM_LONG_RESPONSE;\r
139 }\r
140\r
141 // Clear Status register static flags\r
93b429fc 142 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
633724f4 143\r
93b429fc 144 // Write to command argument register\r
145 MmioWrite32 (MCI_ARGUMENT_REG, Argument);\r
633724f4 146\r
93b429fc 147 // Write to command register\r
148 MmioWrite32 (MCI_COMMAND_REG, Cmd);\r
633724f4 149\r
dad28de1 150 DoneMask = (Cmd & MCI_CPSM_WAIT_RESPONSE)\r
151 ? (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_ERROR)\r
152 : (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_ERROR);\r
153 do {\r
93b429fc 154 Status = MmioRead32 (MCI_STATUS_REG);\r
dad28de1 155 } while (! (Status & DoneMask));\r
633724f4 156\r
dad28de1 157 if ((Status & MCI_STATUS_CMD_ERROR)) {\r
158 // Clear Status register error flags\r
159 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_ERROR);\r
3402aac7 160\r
633724f4 161 if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {\r
93b429fc 162 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 163 RetVal = EFI_NO_RESPONSE;\r
633724f4 164 } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {\r
93b429fc 165 //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 166 RetVal = EFI_TIMEOUT;\r
dad28de1 167 } else if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
633724f4 168 // The CMD1 and response type R3 do not contain CRC. We should ignore the CRC failed Status.\r
169 RetVal = EFI_CRC_ERROR;\r
633724f4 170 }\r
171 }\r
172\r
93b429fc 173 // Disable Command Path\r
174 CmdCtrlReg = MmioRead32 (MCI_COMMAND_REG);\r
175 MmioWrite32 (MCI_COMMAND_REG, (CmdCtrlReg & ~MCI_CPSM_ENABLE));\r
176 return RetVal;\r
633724f4 177}\r
178\r
179EFI_STATUS\r
180MciReceiveResponse (\r
16d88c2d 181 IN EFI_MMC_HOST_PROTOCOL *This,\r
182 IN MMC_RESPONSE_TYPE Type,\r
183 IN UINT32* Buffer\r
633724f4 184 )\r
185{\r
186 if (Buffer == NULL) {\r
187 return EFI_INVALID_PARAMETER;\r
188 }\r
189\r
93b429fc 190 if ( (Type == MMC_RESPONSE_TYPE_R1)\r
191 || (Type == MMC_RESPONSE_TYPE_R1b)\r
192 || (Type == MMC_RESPONSE_TYPE_R3)\r
193 || (Type == MMC_RESPONSE_TYPE_R6)\r
194 || (Type == MMC_RESPONSE_TYPE_R7))\r
633724f4 195 {\r
93b429fc 196 Buffer[0] = MmioRead32 (MCI_RESPONSE3_REG);\r
633724f4 197 } else if (Type == MMC_RESPONSE_TYPE_R2) {\r
93b429fc 198 Buffer[0] = MmioRead32 (MCI_RESPONSE0_REG);\r
199 Buffer[1] = MmioRead32 (MCI_RESPONSE1_REG);\r
200 Buffer[2] = MmioRead32 (MCI_RESPONSE2_REG);\r
201 Buffer[3] = MmioRead32 (MCI_RESPONSE3_REG);\r
633724f4 202 }\r
203\r
204 return EFI_SUCCESS;\r
205}\r
206\r
207EFI_STATUS\r
208MciReadBlockData (\r
16d88c2d 209 IN EFI_MMC_HOST_PROTOCOL *This,\r
210 IN EFI_LBA Lba,\r
211 IN UINTN Length,\r
212 IN UINT32* Buffer\r
633724f4 213 )\r
214{\r
215 UINTN Loop;\r
216 UINTN Finish;\r
217 UINTN Status;\r
218 EFI_STATUS RetVal;\r
219 UINTN DataCtrlReg;\r
bb058bcd 220 EFI_TPL Tpl;\r
633724f4 221\r
222 RetVal = EFI_SUCCESS;\r
223\r
224 // Read data from the RX FIFO\r
225 Loop = 0;\r
226 Finish = MMCI0_BLOCKLEN / 4;\r
3402aac7 227\r
bb058bcd
OM
228 // Raise the TPL at the highest level to disable Interrupts.\r
229 Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
230\r
633724f4 231 do {\r
232 // Read the Status flags\r
93b429fc 233 Status = MmioRead32 (MCI_STATUS_REG);\r
633724f4 234\r
235 // Do eight reads if possible else a single read\r
236 if (Status & MCI_STATUS_CMD_RXFIFOHALFFULL) {\r
237 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
238 Loop++;\r
239 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
240 Loop++;\r
241 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
242 Loop++;\r
243 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
244 Loop++;\r
245 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
246 Loop++;\r
247 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
248 Loop++;\r
249 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
250 Loop++;\r
251 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
252 Loop++;\r
253 } else if (Status & MCI_STATUS_CMD_RXDATAAVAILBL) {\r
254 Buffer[Loop] = MmioRead32(MCI_FIFO_REG);\r
255 Loop++;\r
256 } else {\r
257 //Check for error conditions and timeouts\r
93b429fc 258 if (Status & MCI_STATUS_CMD_DATATIMEOUT) {\r
259 DEBUG ((EFI_D_ERROR, "MciReadBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 260 RetVal = EFI_TIMEOUT;\r
261 break;\r
93b429fc 262 } else if (Status & MCI_STATUS_CMD_DATACRCFAIL) {\r
263 DEBUG ((EFI_D_ERROR, "MciReadBlockData(): CRC Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 264 RetVal = EFI_CRC_ERROR;\r
265 break;\r
93b429fc 266 } else if (Status & MCI_STATUS_CMD_START_BIT_ERROR) {\r
267 DEBUG ((EFI_D_ERROR, "MciReadBlockData(): Start-bit Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 268 RetVal = EFI_NO_RESPONSE;\r
269 break;\r
270 }\r
271 }\r
272 //clear RX over run flag\r
273 if(Status & MCI_STATUS_CMD_RXOVERRUN) {\r
274 MmioWrite32(MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_RXOVERRUN);\r
275 }\r
276 } while ((Loop < Finish));\r
277\r
bb058bcd
OM
278 // Restore Tpl\r
279 gBS->RestoreTPL (Tpl);\r
280\r
93b429fc 281 // Clear Status flags\r
282 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
633724f4 283\r
93b429fc 284 //Disable Data path\r
285 DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);\r
286 MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));\r
633724f4 287\r
93b429fc 288 return RetVal;\r
633724f4 289}\r
290\r
291EFI_STATUS\r
292MciWriteBlockData (\r
16d88c2d 293 IN EFI_MMC_HOST_PROTOCOL *This,\r
294 IN EFI_LBA Lba,\r
295 IN UINTN Length,\r
296 IN UINT32* Buffer\r
633724f4 297 )\r
298{\r
299 UINTN Loop;\r
300 UINTN Finish;\r
301 UINTN Timer;\r
302 UINTN Status;\r
303 EFI_STATUS RetVal;\r
304 UINTN DataCtrlReg;\r
bb058bcd 305 EFI_TPL Tpl;\r
633724f4 306\r
307 RetVal = EFI_SUCCESS;\r
308\r
309 // Write the data to the TX FIFO\r
310 Loop = 0;\r
311 Finish = MMCI0_BLOCKLEN / 4;\r
312 Timer = MMCI0_TIMEOUT * 100;\r
bb058bcd
OM
313\r
314 // Raise the TPL at the highest level to disable Interrupts.\r
315 Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
316\r
633724f4 317 do {\r
318 // Read the Status flags\r
93b429fc 319 Status = MmioRead32 (MCI_STATUS_REG);\r
633724f4 320\r
321 // Do eight writes if possible else a single write\r
322 if (Status & MCI_STATUS_CMD_TXFIFOHALFEMPTY) {\r
323 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
324 Loop++;\r
325 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
326 Loop++;\r
327 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
328 Loop++;\r
329 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
330 Loop++;\r
331 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
332 Loop++;\r
333 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
334 Loop++;\r
335 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
336 Loop++;\r
337 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
338 Loop++;\r
4f8c9ae0 339 } else if (!(Status & MCI_STATUS_CMD_TXFIFOFULL)) {\r
633724f4 340 MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
341 Loop++;\r
342 } else {\r
93b429fc 343 // Check for error conditions and timeouts\r
344 if (Status & MCI_STATUS_CMD_DATATIMEOUT) {\r
345 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 346 RetVal = EFI_TIMEOUT;\r
347 goto Exit;\r
93b429fc 348 } else if (Status & MCI_STATUS_CMD_DATACRCFAIL) {\r
349 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): CRC Error! Response:0x%X Status:0x%x\n", MmioRead32 (MCI_RESPONSE0_REG), Status));\r
633724f4 350 RetVal = EFI_CRC_ERROR;\r
351 goto Exit;\r
93b429fc 352 } else if (Status & MCI_STATUS_CMD_TX_UNDERRUN) {\r
633724f4 353 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
354 RetVal = EFI_BUFFER_TOO_SMALL;\r
355 ASSERT(0);\r
356 goto Exit;\r
357 }\r
358 }\r
359 } while (Loop < Finish);\r
360\r
bb058bcd
OM
361 // Restore Tpl\r
362 gBS->RestoreTPL (Tpl);\r
363\r
633724f4 364 // Wait for FIFO to drain\r
93b429fc 365 Timer = MMCI0_TIMEOUT * 60;\r
366 Status = MmioRead32 (MCI_STATUS_REG);\r
633724f4 367#ifndef USE_STREAM\r
368 // Single block\r
93b429fc 369 while (((Status & MCI_STATUS_TXDONE) != MCI_STATUS_TXDONE) && Timer) {\r
633724f4 370#else\r
371 // Stream\r
372 while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {\r
373#endif\r
374 NanoSecondDelay(10);\r
93b429fc 375 Status = MmioRead32 (MCI_STATUS_REG);\r
633724f4 376 Timer--;\r
377 }\r
378\r
93b429fc 379 // Clear Status flags\r
380 MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
dad28de1 381\r
633724f4 382 if (Timer == 0) {\r
dad28de1 383 DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of words written 0x%x\n", Loop));\r
633724f4 384 RetVal = EFI_TIMEOUT;\r
385 }\r
386\r
387Exit:\r
93b429fc 388 // Disable Data path\r
389 DataCtrlReg = MmioRead32 (MCI_DATA_CTL_REG);\r
390 MmioWrite32 (MCI_DATA_CTL_REG, (DataCtrlReg & MCI_DATACTL_DISABLE_MASK));\r
391 return RetVal;\r
633724f4 392}\r
393\r
394EFI_STATUS\r
395MciNotifyState (\r
16d88c2d 396 IN EFI_MMC_HOST_PROTOCOL *This,\r
397 IN MMC_STATE State\r
633724f4 398 )\r
399{\r
400 UINT32 Data32;\r
401\r
93b429fc 402 switch (State) {\r
633724f4 403 case MmcInvalidState:\r
93b429fc 404 ASSERT (0);\r
633724f4 405 break;\r
406 case MmcHwInitializationState:\r
407 // If device already turn on then restart it\r
93b429fc 408 Data32 = MmioRead32 (MCI_POWER_CONTROL_REG);\r
633724f4 409 if ((Data32 & 0x2) == MCI_POWER_UP) {\r
93b429fc 410 MCI_TRACE ("MciNotifyState(MmcHwInitializationState): TurnOff MCI");\r
633724f4 411\r
412 // Turn off\r
93b429fc 413 MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0);\r
414 MmioWrite32 (MCI_POWER_CONTROL_REG, 0);\r
415 MicroSecondDelay (100);\r
633724f4 416 }\r
417\r
93b429fc 418 MCI_TRACE ("MciNotifyState(MmcHwInitializationState): TurnOn MCI");\r
633724f4 419 // Setup clock\r
420 // - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz\r
93b429fc 421 MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);\r
633724f4 422\r
423 // Set the voltage\r
93b429fc 424 MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_OPENDRAIN | (15<<2));\r
425 MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_UP);\r
426 MicroSecondDelay (10);\r
427 MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_ON);\r
428 MicroSecondDelay (100);\r
633724f4 429\r
430 // Set Data Length & Data Timer\r
93b429fc 431 MmioWrite32 (MCI_DATA_TIMER_REG, 0xFFFFF);\r
432 MmioWrite32 (MCI_DATA_LENGTH_REG, 8);\r
633724f4 433\r
93b429fc 434 ASSERT ((MmioRead32 (MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);\r
633724f4 435 break;\r
436 case MmcIdleState:\r
93b429fc 437 MCI_TRACE ("MciNotifyState(MmcIdleState)");\r
633724f4 438 break;\r
439 case MmcReadyState:\r
93b429fc 440 MCI_TRACE ("MciNotifyState(MmcReadyState)");\r
633724f4 441 break;\r
442 case MmcIdentificationState:\r
93b429fc 443 MCI_TRACE ("MciNotifyState (MmcIdentificationState)");\r
633724f4 444 break;\r
445 case MmcStandByState:{\r
446 volatile UINT32 PwrCtrlReg;\r
93b429fc 447 MCI_TRACE ("MciNotifyState (MmcStandByState)");\r
633724f4 448\r
449 // Enable MCICMD push-pull drive\r
93b429fc 450 PwrCtrlReg = MmioRead32 (MCI_POWER_CONTROL_REG);\r
633724f4 451 //Disable Open Drain output\r
93b429fc 452 PwrCtrlReg &= ~ (MCI_POWER_OPENDRAIN);\r
453 MmioWrite32 (MCI_POWER_CONTROL_REG, PwrCtrlReg);\r
633724f4 454\r
455 // Set MMCI0 clock to 4MHz (24MHz may be possible with cache enabled)\r
456 //\r
457 // Note: Increasing clock speed causes TX FIFO under-run errors.\r
458 // So careful when optimising this driver for higher performance.\r
459 //\r
460 MmioWrite32(MCI_CLOCK_CONTROL_REG,0x02 | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);\r
461 // Set MMCI0 clock to 24MHz (by bypassing the divider)\r
462 //MmioWrite32(MCI_CLOCK_CONTROL_REG,MCI_CLOCK_BYPASS | MCI_CLOCK_ENABLE);\r
463 break;\r
464 }\r
465 case MmcTransferState:\r
93b429fc 466 //MCI_TRACE ("MciNotifyState(MmcTransferState)");\r
633724f4 467 break;\r
468 case MmcSendingDataState:\r
93b429fc 469 MCI_TRACE ("MciNotifyState(MmcSendingDataState)");\r
633724f4 470 break;\r
471 case MmcReceiveDataState:\r
93b429fc 472 MCI_TRACE ("MciNotifyState(MmcReceiveDataState)");\r
633724f4 473 break;\r
474 case MmcProgrammingState:\r
93b429fc 475 MCI_TRACE ("MciNotifyState(MmcProgrammingState)");\r
633724f4 476 break;\r
477 case MmcDisconnectState:\r
93b429fc 478 MCI_TRACE ("MciNotifyState(MmcDisconnectState)");\r
633724f4 479 break;\r
480 default:\r
93b429fc 481 ASSERT (0);\r
633724f4 482 }\r
483 return EFI_SUCCESS;\r
484}\r
485\r
486EFI_GUID mPL180MciDevicePathGuid = EFI_CALLER_ID_GUID;\r
487\r
488EFI_STATUS\r
489MciBuildDevicePath (\r
16d88c2d 490 IN EFI_MMC_HOST_PROTOCOL *This,\r
491 IN EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
633724f4 492 )\r
493{\r
494 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
495\r
93b429fc 496 NewDevicePathNode = CreateDeviceNode (HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH));\r
497 CopyGuid (& ((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &mPL180MciDevicePathGuid);\r
633724f4 498\r
499 *DevicePath = NewDevicePathNode;\r
500 return EFI_SUCCESS;\r
501}\r
502\r
503EFI_MMC_HOST_PROTOCOL gMciHost = {\r
16d88c2d 504 MMC_HOST_PROTOCOL_REVISION,\r
633724f4 505 MciIsCardPresent,\r
506 MciIsReadOnly,\r
507 MciBuildDevicePath,\r
508 MciNotifyState,\r
509 MciSendCommand,\r
510 MciReceiveResponse,\r
511 MciReadBlockData,\r
512 MciWriteBlockData\r
513};\r
514\r
515EFI_STATUS\r
516PL180MciDxeInitialize (\r
517 IN EFI_HANDLE ImageHandle,\r
518 IN EFI_SYSTEM_TABLE *SystemTable\r
519 )\r
520{\r
521 EFI_STATUS Status;\r
93b429fc 522 EFI_HANDLE Handle;\r
523\r
524 Handle = NULL;\r
633724f4 525\r
93b429fc 526 MCI_TRACE ("PL180MciDxeInitialize()");\r
633724f4 527\r
528 //Publish Component Name, BlockIO protocol interfaces\r
529 Status = gBS->InstallMultipleProtocolInterfaces (\r
3402aac7 530 &Handle,\r
633724f4 531 &gEfiMmcHostProtocolGuid, &gMciHost,\r
532 NULL\r
533 );\r
534 ASSERT_EFI_ERROR (Status);\r
535\r
536 return EFI_SUCCESS;\r
537}\r