]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
ArmPlatformPkg/PL180MciDxe: Increased the TPL at the highest priority to disable...
[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
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
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
bb058bcd
OM
227 \r
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
339 } else if ((Status & MCI_STATUS_CMD_TXFIFOEMPTY)) {\r
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
530 &Handle, \r
531 &gEfiMmcHostProtocolGuid, &gMciHost,\r
532 NULL\r
533 );\r
534 ASSERT_EFI_ERROR (Status);\r
535\r
536 return EFI_SUCCESS;\r
537}\r