]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
ArmPlatformPkg: PL061 - rewrite the hardware interaction
[mirror_edk2.git] / ArmPlatformPkg / Drivers / PL180MciDxe / PL180Mci.c
index 313f2af9fdc568b083e7346a694370c74ed900a9..688cd8a98ced2b540ced7c4c7c7bfd5174ef86c4 100644 (file)
@@ -2,14 +2,14 @@
   This file implement the MMC Host Protocol for the ARM PrimeCell PL180.\r
 \r
   Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
-  \r
-  This program and the accompanying materials                          \r
-  are licensed and made available under the terms and conditions of the BSD License         \r
-  which accompanies this distribution.  The full text of the license may be found at        \r
-  http://opensource.org/licenses/bsd-license.php                                            \r
 \r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
 **/\r
 \r
@@ -118,6 +118,7 @@ MciSendCommand (
   UINT32  Cmd;\r
   UINTN   RetVal;\r
   UINTN   CmdCtrlReg;\r
+  UINT32  DoneMask;\r
 \r
   RetVal = EFI_SUCCESS;\r
 \r
@@ -146,54 +147,29 @@ MciSendCommand (
   // Write to command register\r
   MmioWrite32 (MCI_COMMAND_REG, Cmd);\r
 \r
-  if (Cmd & MCI_CPSM_WAIT_RESPONSE) {\r
+  DoneMask  = (Cmd & MCI_CPSM_WAIT_RESPONSE)\r
+                ? (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_ERROR)\r
+                : (MCI_STATUS_CMD_SENT    | MCI_STATUS_CMD_ERROR);\r
+  do {\r
     Status = MmioRead32 (MCI_STATUS_REG);\r
-    while (!(Status & (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT | MCI_STATUS_CMD_START_BIT_ERROR))) {\r
-      Status = MmioRead32(MCI_STATUS_REG);\r
-    }\r
+  } while (! (Status & DoneMask));\r
+\r
+  if ((Status & MCI_STATUS_CMD_ERROR)) {\r
+    // Clear Status register error flags\r
+    MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_ERROR);\r
 \r
     if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {\r
       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
       RetVal = EFI_NO_RESPONSE;\r
-      goto Exit;\r
     } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {\r
       //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n", (Cmd & 0x3F), MmioRead32 (MCI_RESPONSE0_REG), Status));\r
       RetVal = EFI_TIMEOUT;\r
-      goto Exit;\r
-    } else if ((! (MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
+    } else if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
       // The CMD1 and response type R3 do not contain CRC. We should ignore the CRC failed Status.\r
       RetVal = EFI_CRC_ERROR;\r
-      goto Exit;\r
-    } else {\r
-      RetVal =  EFI_SUCCESS;\r
-      goto Exit;\r
-    }\r
-  } else {\r
-    Status = MmioRead32(MCI_STATUS_REG);\r
-    while (!(Status & (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT| MCI_STATUS_CMD_START_BIT_ERROR))) {\r
-      Status = MmioRead32(MCI_STATUS_REG);\r
-    }\r
-\r
-    if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {\r
-      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
-      RetVal = EFI_NO_RESPONSE;\r
-      goto Exit;\r
-    } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {\r
-        //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));\r
-      RetVal = EFI_TIMEOUT;\r
-      goto Exit;\r
-    } else\r
-    if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {\r
-        // The CMD1 does not contain CRC. We should ignore the CRC failed Status.\r
-      RetVal = EFI_CRC_ERROR;\r
-      goto Exit;\r
-    } else {\r
-      RetVal = EFI_SUCCESS;\r
-      goto Exit;\r
     }\r
   }\r
 \r
-Exit:\r
   // Disable Command Path\r
   CmdCtrlReg = MmioRead32 (MCI_COMMAND_REG);\r
   MmioWrite32 (MCI_COMMAND_REG, (CmdCtrlReg & ~MCI_CPSM_ENABLE));\r
@@ -241,12 +217,17 @@ MciReadBlockData (
   UINTN Status;\r
   EFI_STATUS RetVal;\r
   UINTN  DataCtrlReg;\r
+  EFI_TPL Tpl;\r
 \r
   RetVal = EFI_SUCCESS;\r
 \r
   // Read data from the RX FIFO\r
   Loop   = 0;\r
   Finish = MMCI0_BLOCKLEN / 4;\r
+\r
+  // Raise the TPL at the highest level to disable Interrupts.\r
+  Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
   do {\r
     // Read the Status flags\r
     Status = MmioRead32 (MCI_STATUS_REG);\r
@@ -294,6 +275,9 @@ MciReadBlockData (
     }\r
   } while ((Loop < Finish));\r
 \r
+  // Restore Tpl\r
+  gBS->RestoreTPL (Tpl);\r
+\r
   // Clear Status flags\r
   MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
 \r
@@ -318,6 +302,7 @@ MciWriteBlockData (
   UINTN Status;\r
   EFI_STATUS RetVal;\r
   UINTN  DataCtrlReg;\r
+  EFI_TPL Tpl;\r
 \r
   RetVal = EFI_SUCCESS;\r
 \r
@@ -325,6 +310,10 @@ MciWriteBlockData (
   Loop   = 0;\r
   Finish = MMCI0_BLOCKLEN / 4;\r
   Timer  = MMCI0_TIMEOUT * 100;\r
+\r
+  // Raise the TPL at the highest level to disable Interrupts.\r
+  Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
   do {\r
     // Read the Status flags\r
     Status = MmioRead32 (MCI_STATUS_REG);\r
@@ -347,7 +336,7 @@ MciWriteBlockData (
       Loop++;\r
       MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
       Loop++;\r
-    } else if ((Status & MCI_STATUS_CMD_TXFIFOEMPTY)) {\r
+    } else if (!(Status & MCI_STATUS_CMD_TXFIFOFULL)) {\r
         MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);\r
         Loop++;\r
     } else {\r
@@ -369,6 +358,9 @@ MciWriteBlockData (
     }\r
   } while (Loop < Finish);\r
 \r
+  // Restore Tpl\r
+  gBS->RestoreTPL (Tpl);\r
+\r
   // Wait for FIFO to drain\r
   Timer  = MMCI0_TIMEOUT * 60;\r
   Status = MmioRead32 (MCI_STATUS_REG);\r
@@ -384,15 +376,11 @@ MciWriteBlockData (
     Timer--;\r
   }\r
 \r
-  if (Timer == 0) {\r
-    DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of bytes written 0x%x\n",Loop));\r
-    ASSERT (Timer > 0);\r
-    return EFI_TIMEOUT;\r
-  }\r
-\r
   // Clear Status flags\r
   MmioWrite32 (MCI_CLEAR_STATUS_REG, MCI_CLR_ALL_STATUS);\r
+\r
   if (Timer == 0) {\r
+    DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of words written 0x%x\n", Loop));\r
     RetVal = EFI_TIMEOUT;\r
   }\r
 \r
@@ -431,7 +419,6 @@ MciNotifyState (
     // Setup clock\r
     //  - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz\r
     MmioWrite32 (MCI_CLOCK_CONTROL_REG, 0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);\r
-    //MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE);\r
 \r
     // Set the voltage\r
     MmioWrite32 (MCI_POWER_CONTROL_REG, MCI_POWER_OPENDRAIN | (15<<2));\r
@@ -534,13 +521,29 @@ PL180MciDxeInitialize (
   EFI_STATUS    Status;\r
   EFI_HANDLE    Handle;\r
 \r
+  DEBUG ((EFI_D_WARN, "Probing ID registers at 0x%lx for a PL180\n",\r
+    MCI_PERIPH_ID_REG0));\r
+\r
+  // Check if this is a PL180\r
+  if (MmioRead8 (MCI_PERIPH_ID_REG0) != MCI_PERIPH_ID0 ||\r
+      MmioRead8 (MCI_PERIPH_ID_REG1) != MCI_PERIPH_ID1 ||\r
+      MmioRead8 (MCI_PERIPH_ID_REG2) != MCI_PERIPH_ID2 ||\r
+      MmioRead8 (MCI_PERIPH_ID_REG3) != MCI_PERIPH_ID3 ||\r
+      MmioRead8 (MCI_PCELL_ID_REG0)  != MCI_PCELL_ID0  ||\r
+      MmioRead8 (MCI_PCELL_ID_REG1)  != MCI_PCELL_ID1  ||\r
+      MmioRead8 (MCI_PCELL_ID_REG2)  != MCI_PCELL_ID2  ||\r
+      MmioRead8 (MCI_PCELL_ID_REG3)  != MCI_PCELL_ID3) {\r
+\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
   Handle = NULL;\r
 \r
   MCI_TRACE ("PL180MciDxeInitialize()");\r
 \r
   //Publish Component Name, BlockIO protocol interfaces\r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &Handle, \r
+                  &Handle,\r
                   &gEfiMmcHostProtocolGuid,         &gMciHost,\r
                   NULL\r
                   );\r