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