summaryrefslogtreecommitdiff
path: root/ArmPlatformPkg/Drivers
diff options
context:
space:
mode:
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>2011-07-01 15:40:16 +0000
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>2011-07-01 15:40:16 +0000
commit633724f462a7117bc26838e66825e3b1bec506cc (patch)
treef286b27d4986f0b1cbf32495560df22eb3ddbb66 /ArmPlatformPkg/Drivers
parent5cc45b70c310f853f28b2351f3d93109ff858dcf (diff)
downloadedk2-platforms-633724f462a7117bc26838e66825e3b1bec506cc.tar.xz
ArmPkg: Move ARM Platform drivers from ArmPkg/Drivers/ to ArmPlatformPkg/Drivers/ (2)
... svn did not like my way to move folder from one directory to another one :-/ git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11957 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPlatformPkg/Drivers')
-rw-r--r--ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c537
-rw-r--r--ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.h119
-rwxr-xr-xArmPlatformPkg/Drivers/PL180MciDxe/PL180MciDxe.inf52
-rw-r--r--ArmPlatformPkg/Drivers/PL301Axi/PL301Axi.c108
-rwxr-xr-xArmPlatformPkg/Drivers/PL301Axi/PL301Axi.inf27
-rw-r--r--ArmPlatformPkg/Drivers/PL310L2Cache/PL310L2Cache.c126
-rwxr-xr-xArmPlatformPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf31
-rw-r--r--ArmPlatformPkg/Drivers/PL34xDmc/PL341Dmc.c221
-rwxr-xr-xArmPlatformPkg/Drivers/PL34xDmc/PL341Dmc.inf29
-rwxr-xr-xArmPlatformPkg/Drivers/PL35xSmc/InitializeSMC.S196
-rwxr-xr-xArmPlatformPkg/Drivers/PL35xSmc/InitializeSMC.asm153
-rwxr-xr-xArmPlatformPkg/Drivers/PL35xSmc/PL35xSmc.inf29
12 files changed, 1628 insertions, 0 deletions
diff --git a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
new file mode 100644
index 0000000000..697e33f0d0
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.c
@@ -0,0 +1,537 @@
+/** @file
+ This file implement the MMC Host Protocol for the ARM PrimeCell PL180.
+
+ Copyright (c) 2011, ARM Limited. All rights reserved.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PL180Mci.h"
+
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+
+EFI_MMC_HOST_PROTOCOL *gpMmcHost;
+
+// Untested ...
+//#define USE_STREAM
+
+#define MMCI0_BLOCKLEN 512
+#define MMCI0_POW2_BLOCKLEN 9
+#define MMCI0_TIMEOUT 1000
+
+BOOLEAN
+MciIsPowerOn (
+ VOID
+ )
+{
+ return ((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
+}
+
+EFI_STATUS
+MciInitialize (
+ VOID
+ )
+{
+ MCI_TRACE("MciInitialize()");
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+MciIsCardPresent (
+ VOID
+ )
+{
+ return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 1);
+}
+
+BOOLEAN
+MciIsReadOnly (
+ VOID
+ )
+{
+ return (MmioRead32(FixedPcdGet32(PcdPL180SysMciRegAddress)) & 2);
+}
+
+#if 0
+//Note: This function has been commented out because it is not used yet.
+// This function could be used to remove the hardcoded BlockLen used
+// in MciPrepareDataPath
+
+// Convert block size to 2^n
+STATIC
+UINT32
+GetPow2BlockLen (
+ IN UINT32 BlockLen
+ )
+{
+ UINTN Loop;
+ UINTN Pow2BlockLen;
+
+ Loop = 0x8000;
+ Pow2BlockLen = 15;
+ do {
+ Loop = (Loop >> 1) & 0xFFFF;
+ Pow2BlockLen--;
+ } while (Pow2BlockLen && (!(Loop & BlockLen)));
+
+ return Pow2BlockLen;
+}
+#endif
+
+VOID
+MciPrepareDataPath (
+ IN UINTN TransferDirection
+ )
+{
+ // Set Data Length & Data Timer
+ MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFFFF);
+ MmioWrite32(MCI_DATA_LENGTH_REG,MMCI0_BLOCKLEN);
+
+#ifndef USE_STREAM
+ //Note: we are using a hardcoded BlockLen (=512). If we decide to use a variable size, we could
+ // compute the pow2 of BlockLen with the above function GetPow2BlockLen()
+ MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | (MMCI0_POW2_BLOCKLEN << 4));
+#else
+ MmioWrite32(MCI_DATA_CTL_REG, MCI_DATACTL_ENABLE | MCI_DATACTL_DMA_ENABLE | TransferDirection | MCI_DATACTL_STREAM_TRANS);
+#endif
+}
+
+EFI_STATUS
+MciSendCommand (
+ IN MMC_CMD MmcCmd,
+ IN UINT32 Argument
+ )
+{
+ UINT32 Status;
+ UINT32 Cmd;
+ UINTN RetVal;
+ UINTN CmdCtrlReg;
+
+ RetVal = EFI_SUCCESS;
+
+ if ((MmcCmd == MMC_CMD17) || (MmcCmd == MMC_CMD11)) {
+ MciPrepareDataPath(MCI_DATACTL_CARD_TO_CONT);
+ } else if ((MmcCmd == MMC_CMD24) || (MmcCmd == MMC_CMD20)) {
+ MciPrepareDataPath(MCI_DATACTL_CONT_TO_CARD);
+ }
+
+ // Create Command for PL180
+ Cmd = (MMC_GET_INDX(MmcCmd) & INDX_MASK) | MCI_CPSM_ENABLED;
+ if (MmcCmd & MMC_CMD_WAIT_RESPONSE) {
+ Cmd |= MCI_CPSM_WAIT_RESPONSE;
+ }
+
+ if (MmcCmd & MMC_CMD_LONG_RESPONSE) {
+ Cmd |= MCI_CPSM_LONG_RESPONSE;
+ }
+
+ // Clear Status register static flags
+ MmioWrite32(MCI_CLEAR_STATUS_REG,0x7FF);
+
+ //Write to command argument register
+ MmioWrite32(MCI_ARGUMENT_REG,Argument);
+
+ //Write to command register
+ MmioWrite32(MCI_COMMAND_REG,Cmd);
+
+ if (Cmd & MCI_CPSM_WAIT_RESPONSE) {
+ Status = MmioRead32(MCI_STATUS_REG);
+ while (!(Status & (MCI_STATUS_CMD_RESPEND | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT | MCI_STATUS_CMD_START_BIT_ERROR))) {
+ Status = MmioRead32(MCI_STATUS_REG);
+ }
+
+ if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {
+ DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_NO_RESPONSE;
+ goto Exit;
+ } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {
+ //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_TIMEOUT;
+ goto Exit;
+ } else if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {
+ // The CMD1 and response type R3 do not contain CRC. We should ignore the CRC failed Status.
+ RetVal = EFI_CRC_ERROR;
+ goto Exit;
+ } else {
+ RetVal = EFI_SUCCESS;
+ goto Exit;
+ }
+ } else {
+ Status = MmioRead32(MCI_STATUS_REG);
+ while (!(Status & (MCI_STATUS_CMD_SENT | MCI_STATUS_CMD_CMDCRCFAIL | MCI_STATUS_CMD_CMDTIMEOUT| MCI_STATUS_CMD_START_BIT_ERROR))) {
+ Status = MmioRead32(MCI_STATUS_REG);
+ }
+
+ if ((Status & MCI_STATUS_CMD_START_BIT_ERROR)) {
+ DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) Start bit Error! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_NO_RESPONSE;
+ goto Exit;
+ } else if ((Status & MCI_STATUS_CMD_CMDTIMEOUT)) {
+ //DEBUG ((EFI_D_ERROR, "MciSendCommand(CmdIndex:%d) TIMEOUT! Response:0x%X Status:0x%x\n",(Cmd & 0x3F),MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_TIMEOUT;
+ goto Exit;
+ } else
+ if ((!(MmcCmd & MMC_CMD_NO_CRC_RESPONSE)) && (Status & MCI_STATUS_CMD_CMDCRCFAIL)) {
+ // The CMD1 does not contain CRC. We should ignore the CRC failed Status.
+ RetVal = EFI_CRC_ERROR;
+ goto Exit;
+ } else {
+ RetVal = EFI_SUCCESS;
+ goto Exit;
+ }
+ }
+
+Exit:
+ //Disable Command Path
+ CmdCtrlReg = MmioRead32(MCI_COMMAND_REG);
+ MmioWrite32(MCI_COMMAND_REG, (CmdCtrlReg & ~MCI_CPSM_ENABLED));
+ return RetVal;
+}
+
+EFI_STATUS
+MciReceiveResponse (
+ IN MMC_RESPONSE_TYPE Type,
+ IN UINT32* Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Type == MMC_RESPONSE_TYPE_R1) || (Type == MMC_RESPONSE_TYPE_R1b) ||
+ (Type == MMC_RESPONSE_TYPE_R3) || (Type == MMC_RESPONSE_TYPE_R6) ||
+ (Type == MMC_RESPONSE_TYPE_R7))
+ {
+ Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
+ Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
+ } else if (Type == MMC_RESPONSE_TYPE_R2) {
+ Buffer[0] = MmioRead32(MCI_RESPONSE0_REG);
+ Buffer[1] = MmioRead32(MCI_RESPONSE1_REG);
+ Buffer[2] = MmioRead32(MCI_RESPONSE2_REG);
+ Buffer[3] = MmioRead32(MCI_RESPONSE3_REG);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MciReadBlockData (
+ IN EFI_LBA Lba,
+ IN UINTN Length,
+ IN UINT32* Buffer
+ )
+{
+ UINTN Loop;
+ UINTN Finish;
+ UINTN Status;
+ EFI_STATUS RetVal;
+ UINTN DataCtrlReg;
+
+ RetVal = EFI_SUCCESS;
+
+ // Read data from the RX FIFO
+ Loop = 0;
+ Finish = MMCI0_BLOCKLEN / 4;
+ do {
+ // Read the Status flags
+ Status = MmioRead32(MCI_STATUS_REG);
+
+ // Do eight reads if possible else a single read
+ if (Status & MCI_STATUS_CMD_RXFIFOHALFFULL) {
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ } else if (Status & MCI_STATUS_CMD_RXDATAAVAILBL) {
+ Buffer[Loop] = MmioRead32(MCI_FIFO_REG);
+ Loop++;
+ } else {
+ //Check for error conditions and timeouts
+ if(Status & MCI_STATUS_CMD_DATATIMEOUT) {
+ DEBUG ((EFI_D_ERROR, "MciReadBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_TIMEOUT;
+ break;
+ } else if(Status & MCI_STATUS_CMD_DATACRCFAIL) {
+ DEBUG ((EFI_D_ERROR, "MciReadBlockData(): CRC Error! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_CRC_ERROR;
+ break;
+ } else if(Status & MCI_STATUS_CMD_START_BIT_ERROR) {
+ DEBUG ((EFI_D_ERROR, "MciReadBlockData(): Start-bit Error! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_NO_RESPONSE;
+ break;
+ }
+ }
+ //clear RX over run flag
+ if(Status & MCI_STATUS_CMD_RXOVERRUN) {
+ MmioWrite32(MCI_CLEAR_STATUS_REG, MCI_STATUS_CMD_RXOVERRUN);
+ }
+ } while ((Loop < Finish));
+
+ //Clear Status flags
+ MmioWrite32(MCI_CLEAR_STATUS_REG, 0x7FF);
+
+ //Disable Data path
+ DataCtrlReg = MmioRead32(MCI_DATA_CTL_REG);
+ MmioWrite32(MCI_DATA_CTL_REG, (DataCtrlReg & 0xFE));
+
+ return RetVal;
+}
+
+EFI_STATUS
+MciWriteBlockData (
+ IN EFI_LBA Lba,
+ IN UINTN Length,
+ IN UINT32* Buffer
+ )
+{
+ UINTN Loop;
+ UINTN Finish;
+ UINTN Timer;
+ UINTN Status;
+ EFI_STATUS RetVal;
+ UINTN DataCtrlReg;
+
+ RetVal = EFI_SUCCESS;
+
+ // Write the data to the TX FIFO
+ Loop = 0;
+ Finish = MMCI0_BLOCKLEN / 4;
+ Timer = MMCI0_TIMEOUT * 100;
+ do {
+ // Read the Status flags
+ Status = MmioRead32(MCI_STATUS_REG);
+
+ // Do eight writes if possible else a single write
+ if (Status & MCI_STATUS_CMD_TXFIFOHALFEMPTY) {
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ } else if ((Status & MCI_STATUS_CMD_TXFIFOEMPTY)) {
+ MmioWrite32(MCI_FIFO_REG, Buffer[Loop]);
+ Loop++;
+ } else {
+ //Check for error conditions and timeouts
+ if(Status & MCI_STATUS_CMD_DATATIMEOUT) {
+ DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): TIMEOUT! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_TIMEOUT;
+ goto Exit;
+ } else if(Status & MCI_STATUS_CMD_DATACRCFAIL) {
+ DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): CRC Error! Response:0x%X Status:0x%x\n",MmioRead32(MCI_RESPONSE0_REG),Status));
+ RetVal = EFI_CRC_ERROR;
+ goto Exit;
+ } else if(Status & MCI_STATUS_CMD_TX_UNDERRUN) {
+ 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));
+ RetVal = EFI_BUFFER_TOO_SMALL;
+ ASSERT(0);
+ goto Exit;
+ }
+ }
+ } while (Loop < Finish);
+
+ // Wait for FIFO to drain
+ Timer = MMCI0_TIMEOUT * 60;
+ Status = MmioRead32(MCI_STATUS_REG);
+#ifndef USE_STREAM
+ // Single block
+ while (((Status & MCI_STATUS_CMD_TXDONE) != MCI_STATUS_CMD_TXDONE) && Timer) {
+#else
+ // Stream
+ while (((Status & MCI_STATUS_CMD_DATAEND) != MCI_STATUS_CMD_DATAEND) && Timer) {
+#endif
+ NanoSecondDelay(10);
+ Status = MmioRead32(MCI_STATUS_REG);
+ Timer--;
+ }
+
+ if(Timer == 0) {
+ DEBUG ((EFI_D_ERROR, "MciWriteBlockData(): Data End timeout Number of bytes written 0x%x\n",Loop));
+ ASSERT(Timer > 0);
+ return EFI_TIMEOUT;
+ }
+
+ //Clear Status flags
+ MmioWrite32(MCI_CLEAR_STATUS_REG, 0x7FF);
+ if (Timer == 0) {
+ RetVal = EFI_TIMEOUT;
+ }
+
+Exit:
+ //Disable Data path
+ DataCtrlReg = MmioRead32(MCI_DATA_CTL_REG);
+ MmioWrite32(MCI_DATA_CTL_REG, (DataCtrlReg & 0xFE));
+ return RetVal;
+}
+
+EFI_STATUS
+MciNotifyState (
+ IN MMC_STATE State
+ )
+{
+ UINT32 Data32;
+
+ switch(State) {
+ case MmcInvalidState:
+ ASSERT(0);
+ break;
+ case MmcHwInitializationState:
+ // If device already turn on then restart it
+ Data32 = MmioRead32(MCI_POWER_CONTROL_REG);
+ if ((Data32 & 0x2) == MCI_POWER_UP) {
+ MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOff MCI");
+
+ // Turn off
+ MmioWrite32(MCI_CLOCK_CONTROL_REG, 0);
+ MmioWrite32(MCI_POWER_CONTROL_REG, 0);
+ MicroSecondDelay(100);
+ }
+
+ MCI_TRACE("MciNotifyState(MmcHwInitializationState): TurnOn MCI");
+ // Setup clock
+ // - 0x1D = 29 => should be the clock divider to be less than 400kHz at MCLK = 24Mhz
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);
+ //MmioWrite32(MCI_CLOCK_CONTROL_REG,0x1D | MCI_CLOCK_ENABLE);
+
+ // Set the voltage
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_OPENDRAIN | (15<<2));
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_UP);
+ MicroSecondDelay(10);
+ MmioWrite32(MCI_POWER_CONTROL_REG,MCI_POWER_ROD | MCI_POWER_OPENDRAIN | (15<<2) | MCI_POWER_ON);
+ MicroSecondDelay(100);
+
+ // Set Data Length & Data Timer
+ MmioWrite32(MCI_DATA_TIMER_REG,0xFFFFF);
+ MmioWrite32(MCI_DATA_LENGTH_REG,8);
+
+ ASSERT((MmioRead32(MCI_POWER_CONTROL_REG) & 0x3) == MCI_POWER_ON);
+ break;
+ case MmcIdleState:
+ MCI_TRACE("MciNotifyState(MmcIdleState)");
+ break;
+ case MmcReadyState:
+ MCI_TRACE("MciNotifyState(MmcReadyState)");
+ break;
+ case MmcIdentificationState:
+ MCI_TRACE("MciNotifyState(MmcIdentificationState)");
+ break;
+ case MmcStandByState:{
+ volatile UINT32 PwrCtrlReg;
+ MCI_TRACE("MciNotifyState(MmcStandByState)");
+
+ // Enable MCICMD push-pull drive
+ PwrCtrlReg = MmioRead32(MCI_POWER_CONTROL_REG);
+ //Disable Open Drain output
+ PwrCtrlReg &=~(MCI_POWER_OPENDRAIN);
+ MmioWrite32(MCI_POWER_CONTROL_REG,PwrCtrlReg);
+
+ // Set MMCI0 clock to 4MHz (24MHz may be possible with cache enabled)
+ //
+ // Note: Increasing clock speed causes TX FIFO under-run errors.
+ // So careful when optimising this driver for higher performance.
+ //
+ MmioWrite32(MCI_CLOCK_CONTROL_REG,0x02 | MCI_CLOCK_ENABLE | MCI_CLOCK_POWERSAVE);
+ // Set MMCI0 clock to 24MHz (by bypassing the divider)
+ //MmioWrite32(MCI_CLOCK_CONTROL_REG,MCI_CLOCK_BYPASS | MCI_CLOCK_ENABLE);
+ break;
+ }
+ case MmcTransferState:
+ //MCI_TRACE("MciNotifyState(MmcTransferState)");
+ break;
+ case MmcSendingDataState:
+ MCI_TRACE("MciNotifyState(MmcSendingDataState)");
+ break;
+ case MmcReceiveDataState:
+ MCI_TRACE("MciNotifyState(MmcReceiveDataState)");
+ break;
+ case MmcProgrammingState:
+ MCI_TRACE("MciNotifyState(MmcProgrammingState)");
+ break;
+ case MmcDisconnectState:
+ MCI_TRACE("MciNotifyState(MmcDisconnectState)");
+ break;
+ default:
+ ASSERT(0);
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_GUID mPL180MciDevicePathGuid = EFI_CALLER_ID_GUID;
+
+EFI_STATUS
+MciBuildDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
+
+ NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH,HW_VENDOR_DP,sizeof(VENDOR_DEVICE_PATH));
+ CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid,&mPL180MciDevicePathGuid);
+
+ *DevicePath = NewDevicePathNode;
+ return EFI_SUCCESS;
+}
+
+EFI_MMC_HOST_PROTOCOL gMciHost = {
+ MciIsCardPresent,
+ MciIsReadOnly,
+ MciBuildDevicePath,
+ MciNotifyState,
+ MciSendCommand,
+ MciReceiveResponse,
+ MciReadBlockData,
+ MciWriteBlockData
+};
+
+EFI_STATUS
+PL180MciDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = NULL;
+
+ MCI_TRACE("PL180MciDxeInitialize()");
+
+ //Publish Component Name, BlockIO protocol interfaces
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiMmcHostProtocolGuid, &gMciHost,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.h b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.h
new file mode 100644
index 0000000000..53a0b1c5af
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180Mci.h
@@ -0,0 +1,119 @@
+/** @file
+ Header for the MMC Host Protocol implementation for the ARM PrimeCell PL180.
+
+ Copyright (c) 2011, ARM Limited. All rights reserved.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PL180_MCI_H
+#define __PL180_MCI_H
+
+#include <Uefi.h>
+
+#include <Protocol/MmcHost.h>
+
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
+
+#define PL180_MCI_DXE_VERSION 0x10
+
+#define MCI_SYSCTL FixedPcdGet32(PcdPL180MciBaseAddress)
+
+#define MCI_POWER_CONTROL_REG (MCI_SYSCTL+0x000)
+#define MCI_CLOCK_CONTROL_REG (MCI_SYSCTL+0x004)
+#define MCI_ARGUMENT_REG (MCI_SYSCTL+0x008)
+#define MCI_COMMAND_REG (MCI_SYSCTL+0x00C)
+#define MCI_RESPCMD_REG (MCI_SYSCTL+0x010)
+#define MCI_RESPONSE0_REG (MCI_SYSCTL+0x014)
+#define MCI_RESPONSE1_REG (MCI_SYSCTL+0x018)
+#define MCI_RESPONSE2_REG (MCI_SYSCTL+0x01C)
+#define MCI_RESPONSE3_REG (MCI_SYSCTL+0x020)
+#define MCI_DATA_TIMER_REG (MCI_SYSCTL+0x024)
+#define MCI_DATA_LENGTH_REG (MCI_SYSCTL+0x028)
+#define MCI_DATA_CTL_REG (MCI_SYSCTL+0x02C)
+#define MCI_DATA_COUNTER (MCI_SYSCTL+0x030)
+#define MCI_STATUS_REG (MCI_SYSCTL+0x034)
+#define MCI_CLEAR_STATUS_REG (MCI_SYSCTL+0x038)
+#define MCI_INT0_MASK_REG (MCI_SYSCTL+0x03C)
+#define MCI_INT1_MASK_REG (MCI_SYSCTL+0x040)
+#define MCI_FIFOCOUNT_REG (MCI_SYSCTL+0x048)
+#define MCI_FIFO_REG (MCI_SYSCTL+0x080)
+
+#define MCI_POWER_UP 0x2
+#define MCI_POWER_ON 0x3
+#define MCI_POWER_OPENDRAIN (1 << 6)
+#define MCI_POWER_ROD (1 << 7)
+
+#define MCI_CLOCK_ENABLE 0x100
+#define MCI_CLOCK_POWERSAVE 0x200
+#define MCI_CLOCK_BYPASS 0x400
+
+#define MCI_STATUS_CMD_CMDCRCFAIL 0x1
+#define MCI_STATUS_CMD_DATACRCFAIL 0x2
+#define MCI_STATUS_CMD_CMDTIMEOUT 0x4
+#define MCI_STATUS_CMD_DATATIMEOUT 0x8
+#define MCI_STATUS_CMD_TX_UNDERRUN 0x10
+#define MCI_STATUS_CMD_RXOVERRUN 0x20
+#define MCI_STATUS_CMD_RESPEND 0x40
+#define MCI_STATUS_CMD_SENT 0x80
+#define MCI_STATUS_CMD_TXDONE (MCI_STATUS_CMD_DATAEND | MCI_STATUS_CMD_DATABLOCKEND)
+#define MCI_STATUS_CMD_DATAEND 0x000100 // Command Status - Data end
+#define MCI_STATUS_CMD_START_BIT_ERROR 0x000200
+#define MCI_STATUS_CMD_DATABLOCKEND 0x000400 // Command Status - Data end
+#define MCI_STATUS_CMD_ACTIVE 0x800
+#define MCI_STATUS_CMD_RXACTIVE (1 << 13)
+#define MCI_STATUS_CMD_RXFIFOHALFFULL 0x008000
+#define MCI_STATUS_CMD_RXFIFOEMPTY 0x080000
+#define MCI_STATUS_CMD_RXDATAAVAILBL (1 << 21)
+#define MCI_STATUS_CMD_TXACTIVE (1 << 12)
+#define MCI_STATUS_CMD_TXFIFOFULL (1 << 16)
+#define MCI_STATUS_CMD_TXFIFOHALFEMPTY (1 << 14)
+#define MCI_STATUS_CMD_TXFIFOEMPTY (1 << 18)
+#define MCI_STATUS_CMD_TXDATAAVAILBL (1 << 20)
+
+#define MCI_DATACTL_ENABLE 1
+#define MCI_DATACTL_CONT_TO_CARD 0
+#define MCI_DATACTL_CARD_TO_CONT 2
+#define MCI_DATACTL_BLOCK_TRANS 0
+#define MCI_DATACTL_STREAM_TRANS 4
+#define MCI_DATACTL_DMA_ENABLE (1 << 3)
+
+#define INDX_MASK 0x3F
+
+#define MCI_CPSM_ENABLED (1 << 10)
+#define MCI_CPSM_WAIT_RESPONSE (1 << 6)
+#define MCI_CPSM_LONG_RESPONSE (1 << 7)
+
+#define MCI_TRACE(txt) DEBUG((EFI_D_BLKIO, "ARM_MCI: " txt "\n"))
+
+EFI_STATUS
+EFIAPI
+MciGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+MciGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif
diff --git a/ArmPlatformPkg/Drivers/PL180MciDxe/PL180MciDxe.inf b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
new file mode 100755
index 0000000000..b6d72e77a4
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL180MciDxe/PL180MciDxe.inf
@@ -0,0 +1,52 @@
+#/** @file
+# INF file for the MMC Host Protocol implementation for the ARM PrimeCell PL180.
+#
+# Copyright (c) 2011, ARM Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL180MciDxe
+ FILE_GUID = 09831032-6fa3-4484-af4f-0a000a8d3a82
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PL180MciDxeInitialize
+
+[Sources.common]
+ PL180Mci.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ ArmLib
+ IoLib
+ TimerLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiMmcHostProtocolGuid
+
+[Pcd]
+ gArmPlatformTokenSpaceGuid.PcdPL180SysMciRegAddress
+ gArmPlatformTokenSpaceGuid.PcdPL180MciBaseAddress
+
+[Depex]
+ TRUE
diff --git a/ArmPlatformPkg/Drivers/PL301Axi/PL301Axi.c b/ArmPlatformPkg/Drivers/PL301Axi/PL301Axi.c
new file mode 100644
index 0000000000..7241f5cef2
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL301Axi/PL301Axi.c
@@ -0,0 +1,108 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+
+#define PL301_QOS_TIDEMARK_MI_0 0x400
+#define PL301_QOS_ACCESSCONTROL_MI_0 0x404
+
+#define PL301_QOS_TIDEMARK_MI_1 0x420
+#define PL301_QOS_ACCESSCONTROL_MI_1 0x424
+
+#define PL301_QOS_TIDEMARK_MI_2 0x440
+#define PL301_QOS_ACCESSCONTROL_MI_2 0x444
+
+#define PL301_AR_ARB_MI_0 0x408
+#define PL301_AW_ARB_MI_0 0x40C
+
+#define PL301_AR_ARB_MI_1 0x428
+#define PL301_AW_ARB_MI_1 0x42C
+
+#define PL301_AR_ARB_MI_2 0x448
+#define PL301_AW_ARB_MI_2 0x44C
+
+#define PL301_MI_1_OFFSET 0x20
+#define PL301_MI_2_OFFSET 0x40
+#define PL301_MI_3_OFFSET 0x60
+#define PL301_MI_4_OFFSET 0x80
+#define PL301_MI_5_OFFSET 0xa0
+
+#define V2P_CA9_FAXI_MI0_TIDEMARK_VAL 0x6
+#define V2P_CA9_FAXI_MI0_ACCESSCNTRL_VAL 0x1
+
+#define V2P_CA9_FAXI_MI1_TIDEMARK_VAL 0x6
+#define V2P_CA9_FAXI_MI1_ACCESSCNTRL_VAL 0x1
+
+#define V2P_CA9_FAXI_MI2_TIDEMARK_VAL 0x6
+#define V2P_CA9_FAXI_MI2_ACCESSCNTRL_VAL 0x1
+
+
+#define FAxiWriteReg(reg,val) MmioWrite32(FAxiBase + reg, val)
+#define FAxiReadReg(reg) MmioRead32(FAxiBase + reg)
+
+// IN FAxiBase
+// Initialize PL301 Dynamic Memory Controller
+VOID PL301AxiInit(UINTN FAxiBase) {
+ // Configure Tidemark Register for Master Port 0 (MI 0)
+ FAxiWriteReg(PL301_QOS_TIDEMARK_MI_0, V2P_CA9_FAXI_MI0_TIDEMARK_VAL);
+
+ // Configure the Access Control Register (MI 0)
+ FAxiWriteReg(PL301_QOS_ACCESSCONTROL_MI_0, V2P_CA9_FAXI_MI0_ACCESSCNTRL_VAL);
+
+ // MP0
+ // Set priority for Read
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x00000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x01000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x02000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x03000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_0, 0x04000200);
+
+ // Set priority for Write
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x00000100);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x01000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x02000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x03000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_0, 0x04000200);
+
+ // MP1
+ // Set priority for Read
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x00000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x01000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x02000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x03000200);
+ FAxiWriteReg(PL301_AR_ARB_MI_1, 0x04000200);
+
+ // Set priority for Write
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x00000100);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x01000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x02000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x03000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_1, 0x04000200);
+
+ // MP2
+ // Set priority for Read
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x00000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x01000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x02000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x03000100);
+ FAxiWriteReg(PL301_AR_ARB_MI_2, 0x04000100);
+
+ // Set priority for Write
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x00000100);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x01000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x02000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x03000200);
+ FAxiWriteReg(PL301_AW_ARB_MI_2, 0x04000200);
+}
diff --git a/ArmPlatformPkg/Drivers/PL301Axi/PL301Axi.inf b/ArmPlatformPkg/Drivers/PL301Axi/PL301Axi.inf
new file mode 100755
index 0000000000..c0fa4d1ca9
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL301Axi/PL301Axi.inf
@@ -0,0 +1,27 @@
+#/* @file
+# Copyright (c) 2011, ARM Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL301Axi
+ FILE_GUID = 2ea84160-aba0-11df-9896-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL301AxiLib
+
+[Sources]
+ PL301Axi.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
diff --git a/ArmPlatformPkg/Drivers/PL310L2Cache/PL310L2Cache.c b/ArmPlatformPkg/Drivers/PL310L2Cache/PL310L2Cache.c
new file mode 100644
index 0000000000..b701978da5
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL310L2Cache/PL310L2Cache.c
@@ -0,0 +1,126 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ArmLib.h>
+#include <Drivers/PL310L2Cache.h>
+#include <Library/PcdLib.h>
+
+#define L2x0WriteReg(reg,val) MmioWrite32(PcdGet32(PcdL2x0ControllerBase) + reg, val)
+#define L2x0ReadReg(reg) MmioRead32(PcdGet32(PcdL2x0ControllerBase) + reg)
+
+// Initialize PL320 L2 Cache Controller
+VOID
+L2x0CacheInit (
+ IN UINTN L2x0Base,
+ IN UINT32 L2x0TagLatencies,
+ IN UINT32 L2x0DataLatencies,
+ IN UINT32 L2x0AuxValue,
+ IN UINT32 L2x0AuxMask,
+ IN BOOLEAN CacheEnabled
+ )
+{
+ UINT32 Data;
+ UINT32 Revision;
+ UINT32 Aux;
+ UINT32 PfCtl;
+ UINT32 PwrCtl;
+
+ // Check if L2x0 is present and is an ARM implementation
+ Data = L2x0ReadReg(L2X0_CACHEID);
+ if ((Data >> 24) != L2X0_CACHEID_IMPLEMENTER_ARM) {
+ ASSERT(0);
+ return;
+ }
+
+ // Check if L2x0 is PL310
+ if (((Data >> 6) & 0xF) != L2X0_CACHEID_PARTNUM_PL310) {
+ ASSERT(0);
+ return;
+ }
+
+ // RTL release
+ Revision = Data & 0x3F;
+
+ // Check if L2x0 is already enabled then we disable it
+ Data = L2x0ReadReg(L2X0_CTRL);
+ if (Data & L2X0_CTRL_ENABLED) {
+ L2x0WriteReg(L2X0_CTRL, L2X0_CTRL_DISABLED);
+ }
+
+ //
+ // Set up global configurations
+ //
+
+ // Auxiliary register: Non-secure interrupt access Control + Event monitor bus enable + SBO
+ Aux = L2X0_AUXCTRL_NSAC | L2X0_AUXCTRL_EM | L2X0_AUXCTRL_SBO;
+ // Use AWCACHE attributes for WA
+ Aux |= L2x0_AUXCTRL_AW_AWCACHE;
+ // Use default Size
+ Data = L2x0ReadReg(L2X0_AUXCTRL);
+ Aux |= Data & L2X0_AUXCTRL_WAYSIZE_MASK;
+ // Use default associativity
+ Aux |= Data & L2X0_AUXCTRL_ASSOCIATIVITY;
+ // Enabled I & D Prefetch
+ Aux |= L2x0_AUXCTRL_IPREFETCH | L2x0_AUXCTRL_DPREFETCH;
+
+ if (Revision >= 5) {
+ // Prefetch Offset Register
+ PfCtl = L2x0ReadReg(L2X0_PFCTRL);
+ // - Prefetch increment set to 0
+ // - Prefetch dropping off
+ // - Double linefills off
+ L2x0WriteReg(L2X0_PFCTRL, PfCtl);
+
+ // Power Control Register - L2X0_PWRCTRL
+ PwrCtl = L2x0ReadReg(L2X0_PWRCTRL);
+ // - Standby when idle off
+ // - Dynamic clock gating off
+ // - Nc,NC-shared dropping off
+ L2x0WriteReg(L2X0_PWRCTRL, PwrCtl);
+ }
+
+ if (Revision >= 2) {
+ L2x0WriteReg(L230_TAG_LATENCY, L2x0TagLatencies);
+ L2x0WriteReg(L230_DATA_LATENCY, L2x0DataLatencies);
+ } else {
+ // PL310 old style latency is not supported yet
+ ASSERT(0);
+ }
+
+ // Set the platform specific values
+ Aux = (Aux & L2x0AuxMask) | L2x0AuxValue;
+
+ // Write Auxiliary value
+ L2x0WriteReg(L2X0_AUXCTRL, Aux);
+
+ //
+ // Invalidate all entries in cache
+ //
+ L2x0WriteReg(L2X0_INVWAY, 0xffff);
+ // Poll cache maintenance register until invalidate operation is complete
+ while(L2x0ReadReg(L2X0_INVWAY) & 0xffff);
+
+ // Write to the Lockdown D and Lockdown I Register 9 if required
+ // - Not required
+
+ // Clear any residual raw interrupts
+ L2x0WriteReg(L2X0_INTCLEAR, 0x1FF);
+
+ // Enable the cache
+ if (CacheEnabled) {
+ L2x0WriteReg(L2X0_CTRL, L2X0_CTRL_ENABLED);
+ }
+}
diff --git a/ArmPlatformPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf b/ArmPlatformPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf
new file mode 100755
index 0000000000..1a95aa85fe
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL310L2Cache/PL310L2CacheSec.inf
@@ -0,0 +1,31 @@
+#/* @file
+# Copyright (c) 2011, ARM Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL310L2Cache
+ FILE_GUID = 16ad4fe0-b5b1-11df-8cbf-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = L2X0CacheLib
+
+[Sources]
+ PL310L2Cache.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdL2x0ControllerBase
diff --git a/ArmPlatformPkg/Drivers/PL34xDmc/PL341Dmc.c b/ArmPlatformPkg/Drivers/PL34xDmc/PL341Dmc.c
new file mode 100644
index 0000000000..ae94def765
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL34xDmc/PL341Dmc.c
@@ -0,0 +1,221 @@
+/** @file
+*
+* Copyright (c) 2011, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Drivers/PL341Dmc.h>
+
+// Macros for writing to DDR2 controller.
+#define DmcWriteReg(reg,val) MmioWrite32(DmcBase + reg, val)
+#define DmcReadReg(reg) MmioRead32(DmcBase + reg)
+
+// Macros for writing/reading to DDR2 PHY controller
+#define DmcPhyWriteReg(reg,val) MmioWrite32(DmcPhyBase + reg, val)
+#define DmcPhyReadReg(reg) MmioRead32(DmcPhyBase + reg)
+
+// Initialise PL341 Dynamic Memory Controller
+VOID
+PL341DmcInit (
+ IN PL341_DMC_CONFIG *DmcConfig
+ )
+{
+ UINTN DmcBase;
+ UINTN Index;
+ UINT32 Chip;
+
+ DmcBase = DmcConfig->base;
+
+ // Set config mode
+ DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_CONFIGURE);
+
+ //
+ // Setup the QoS AXI ID bits
+ //
+ if (DmcConfig->HasQos) {
+ // CLCD AXIID = 000
+ DmcWriteReg(DMC_ID_0_CFG_REG, DMC_ID_CFG_QOS_ENABLE | DMC_ID_CFG_QOS_MIN);
+
+ // Default disable QoS
+ DmcWriteReg(DMC_ID_1_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_2_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_3_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_4_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_5_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_6_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_7_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_8_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_9_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_10_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_11_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_12_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_13_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_14_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ DmcWriteReg(DMC_ID_15_CFG_REG, DMC_ID_CFG_QOS_DISABLE);
+ }
+
+ //
+ // Initialise memory controlller
+ //
+ DmcWriteReg(DMC_REFRESH_PRD_REG, DmcConfig->refresh_prd);
+ DmcWriteReg(DMC_CAS_LATENCY_REG, DmcConfig->cas_latency);
+ DmcWriteReg(DMC_WRITE_LATENCY_REG, DmcConfig->write_latency);
+ DmcWriteReg(DMC_T_MRD_REG, DmcConfig->t_mrd);
+ DmcWriteReg(DMC_T_RAS_REG, DmcConfig->t_ras);
+ DmcWriteReg(DMC_T_RC_REG, DmcConfig->t_rc);
+ DmcWriteReg(DMC_T_RCD_REG, DmcConfig->t_rcd);
+ DmcWriteReg(DMC_T_RFC_REG, DmcConfig->t_rfc);
+ DmcWriteReg(DMC_T_RP_REG, DmcConfig->t_rp);
+ DmcWriteReg(DMC_T_RRD_REG, DmcConfig->t_rrd);
+ DmcWriteReg(DMC_T_WR_REG, DmcConfig->t_wr);
+ DmcWriteReg(DMC_T_WTR_REG, DmcConfig->t_wtr);
+ DmcWriteReg(DMC_T_XP_REG, DmcConfig->t_xp);
+ DmcWriteReg(DMC_T_XSR_REG, DmcConfig->t_xsr);
+ DmcWriteReg(DMC_T_ESR_REG, DmcConfig->t_esr);
+ DmcWriteReg(DMC_T_FAW_REG, DmcConfig->t_faw);
+ DmcWriteReg(DMC_T_WRLAT_DIFF, DmcConfig->t_wdata_en);
+ DmcWriteReg(DMC_T_RDATA_EN, DmcConfig->t_data_en);
+
+ //
+ // Initialise PL341 Mem Config Registers
+ //
+
+ // Set PL341 Memory Config
+ DmcWriteReg(DMC_MEMORY_CONFIG_REG, DmcConfig->MemoryCfg);
+
+ // Set PL341 Memory Config 2
+ DmcWriteReg(DMC_MEMORY_CFG2_REG, DmcConfig->MemoryCfg2);
+
+ // Set PL341 Chip Select <n>
+ DmcWriteReg(DMC_CHIP_0_CFG_REG, DmcConfig->ChipCfg0);
+ DmcWriteReg(DMC_CHIP_1_CFG_REG, DmcConfig->ChipCfg1);
+ DmcWriteReg(DMC_CHIP_2_CFG_REG, DmcConfig->ChipCfg2);
+ DmcWriteReg(DMC_CHIP_3_CFG_REG, DmcConfig->ChipCfg3);
+
+ // Delay
+ for (Index = 0; Index < 10; Index++) {
+ DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // Set PL341 Memory Config 3
+ DmcWriteReg(DMC_MEMORY_CFG3_REG, DmcConfig->MemoryCfg3);
+
+ if (DmcConfig->IsUserCfg) {
+ //
+ // Set Test Chip PHY Registers via PL341 User Config Reg
+ // Note that user_cfgX registers are Write Only
+ //
+ // DLL Freq set = 250MHz - 266MHz
+ //
+ DmcWriteReg(DMC_USER_0_CFG_REG, DmcConfig->User0Cfg);
+
+ // user_config2
+ // ------------
+ // Set defaults before calibrating the DDR2 buffer impendence
+ // - Disable ODT
+ // - Default drive strengths
+ DmcWriteReg(DMC_USER_2_CFG_REG, 0x40000198);
+
+ //
+ // Auto calibrate the DDR2 buffers impendence
+ //
+ while (!(DmcReadReg(DMC_USER_STATUS_REG) & 0x100));
+
+ // Set the output driven strength
+ DmcWriteReg(DMC_USER_2_CFG_REG, 0x40800000 | DmcConfig->User2Cfg);
+
+ //
+ // Set PL341 Feature Control Register
+ //
+ // Disable early BRESP - use to optimise CLCD performance
+ DmcWriteReg(DMC_FEATURE_CRTL_REG, 0x00000001);
+ }
+
+ //
+ // Config memories
+ //
+ for (Chip = 0; Chip < DmcConfig->MaxChip; Chip++) {
+ // Send nop
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_NOP);
+
+ // Pre-charge all
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL);
+
+ // Delay
+ for (Index = 0; Index < 10; Index++) {
+ DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // Set (EMR2) extended mode register 2
+ DmcWriteReg(DMC_DIRECT_CMD_REG,
+ DMC_DIRECT_CMD_CHIP_ADDR(Chip) |
+ DMC_DIRECT_CMD_BANKADDR(2) |
+ DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);
+
+ // Set (EMR3) extended mode register 3
+ DmcWriteReg(DMC_DIRECT_CMD_REG,
+ DMC_DIRECT_CMD_CHIP_ADDR(Chip) |
+ DMC_DIRECT_CMD_BANKADDR(3) |
+ DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);
+
+ //
+ // Set (EMR) Extended Mode Register
+ //
+ // Put into OCD default state
+ DmcWriteReg(DMC_DIRECT_CMD_REG,DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_BANKADDR(1) | DMC_DIRECT_CMD_MEMCMD_EXTMODEREG);
+
+ //
+ // Set (MR) mode register - With DLL reset
+ //
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_EXTMODEREG | DmcConfig->ModeReg | DDR2_MR_DLL_RESET);
+
+ // Pre-charge all
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL);
+ // Auto-refresh
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);
+ // Auto-refresh
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH);
+
+ //
+ // Set (MR) mode register - Without DLL reset
+ //
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_EXTMODEREG | DmcConfig->ModeReg);
+
+ // Delay
+ for (Index = 0; Index < 10; Index++) {
+ DmcReadReg(DMC_STATUS_REG);
+ }
+
+ //
+ // Set (EMR) extended mode register - Enable OCD defaults
+ //
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | (0x00090000) |
+ (1 << DDR_MODESET_SHFT) | (DDR_EMR_OCD_DEFAULT << DDR_EMR_OCD_SHIFT) | DmcConfig->ExtModeReg);
+
+ // Delay
+ for (Index = 0; Index < 10; Index++) {
+ DmcReadReg(DMC_STATUS_REG);
+ }
+
+ // Set (EMR) extended mode register - OCD Exit
+ DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | (0x00090000) |
+ (1 << DDR_MODESET_SHFT) | (DDR_EMR_OCD_NS << DDR_EMR_OCD_SHIFT) | DmcConfig->ExtModeReg);
+ }
+
+ // Move DDR2 Controller to Ready state by issueing GO command
+ DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_GO);
+
+ // wait for ready
+ while (!(DmcReadReg(DMC_STATUS_REG) & DMC_STATUS_READY));
+
+}
diff --git a/ArmPlatformPkg/Drivers/PL34xDmc/PL341Dmc.inf b/ArmPlatformPkg/Drivers/PL34xDmc/PL341Dmc.inf
new file mode 100755
index 0000000000..c24cf3e062
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL34xDmc/PL341Dmc.inf
@@ -0,0 +1,29 @@
+#/* @file
+# Copyright (c) 2011, ARM Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL341Dmc
+ FILE_GUID = edf8da40-aad1-11df-a1f4-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL341DmcLib
+
+[Sources]
+ PL341Dmc.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
+
+[FixedPcd]
diff --git a/ArmPlatformPkg/Drivers/PL35xSmc/InitializeSMC.S b/ArmPlatformPkg/Drivers/PL35xSmc/InitializeSMC.S
new file mode 100755
index 0000000000..789c12cfe6
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL35xSmc/InitializeSMC.S
@@ -0,0 +1,196 @@
+#
+# Copyright (c) 2011, ARM Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http:#opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+
+#include <AsmMacroIoLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+#include <Drivers/PL35xSmc.h>
+
+.text
+
+#Maintain 8 byte alignment
+.align 3
+
+
+GCC_ASM_EXPORT(SMCInitializeNOR)
+GCC_ASM_EXPORT(SMCInitializeSRAM)
+GCC_ASM_EXPORT(SMCInitializePeripherals)
+GCC_ASM_EXPORT(SMCInitializeVRAM)
+
+
+# CS0 CS0-Interf0 NOR1 flash on the motherboard
+# CS1 CS1-Interf0 Reserved for the motherboard
+# CS2 CS2-Interf0 SRAM on the motherboard
+# CS3 CS3-Interf0 memory-mapped Ethernet and USB controllers on the motherboard
+# CS4 CS0-Interf1 NOR2 flash on the motherboard
+# CS5 CS1-Interf1 memory-mapped peripherals
+# CS6 CS2-Interf1 memory-mapped peripherals
+# CS7 CS3-Interf1 system memory-mapped peripherals on the motherboard.
+
+// IN r1 SmcBase
+// IN r2 ChipSelect
+// NOTE: This code is been called before any stack has been setup. It means some registers
+// could be overwritten (case of 'r0')
+ASM_PFX(SMCInitializeNOR):
+#
+# Setup NOR1 (CS0-Interface0)
+#
+
+ # Write to set_cycle register(holding register for NOR 1 cycle register or NAND cycle register)
+ #Read cycle timeout = 0xA (0:3)
+ #Write cycle timeout = 0x3(7:4)
+ #OE Assertion Delay = 0x9(11:8)
+ #WE Assertion delay = 0x3(15:12)
+ #Page cycle timeout = 0x2(19:16)
+ LoadConstantToReg (0x0002393A,r0) @ldr r0, = 0x0002393A
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ # Write to set_opmode register(holding register for NOR 1 opomode register or NAND opmode register)
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000028 = ReadMemoryBurstLength:continuous
+ # 0x00000280 = WriteMemoryBurstLength:continuous
+ # 0x00000800 = Set Address Valid
+ LoadConstantToReg (0x00000AAA,r0) @ldr r0, = 0x00000AAA
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ # Write to direct_cmd register so that the NOR 1 registers(set-cycles and opmode) are updated with holding registers
+ # 0x00000000 = ChipSelect0-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x00400000,r0) @ldr r0, = 0x00400000
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+ bx lr
+
+ASM_PFX(SMCInitializeSRAM):
+#
+# Setup SRAM (CS2-Interface0)
+#
+ LoadConstantToReg (0x00027158,r0) @ldr r0, = 0x00027158
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000800 = Set Address Valid
+ LoadConstantToReg (0x00000802,r0) @ldr r0, = 0x00000802
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ # 0x01000000 = ChipSelect2-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x01400000,r0) @ldr r0, = 0x01400000
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+ bx lr
+
+ASM_PFX(SMCInitializePeripherals):
+#
+# USB/Eth/VRAM (CS3-Interface0)
+#
+ LoadConstantToReg (0x000CD2AA,r0) @ldr r0, = 0x000CD2AA
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000004 = Memory reads are synchronous
+ # 0x00000040 = Memory writes are synchronous
+ LoadConstantToReg (0x00000046,r0) @ldr r0, = 0x00000046
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ # 0x01800000 = ChipSelect3-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x01C00000,r0) @ldr r0, = 0x01C00000
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+#
+# Setup NOR3 (CS0-Interface1)
+#
+ LoadConstantToReg (0x0002393A,r0) @ldr r0, = 0x0002393A
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000028 = ReadMemoryBurstLength:continuous
+ # 0x00000280 = WriteMemoryBurstLength:continuous
+ # 0x00000800 = Set Address Valid
+ LoadConstantToReg (0x00000AAA,r0) @ldr r0, = 0x00000AAA
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ # 0x02000000 = ChipSelect0-Interface 1
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x02400000,r0) @ldr r0, = 0x02400000
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+#
+# Setup Peripherals (CS3-Interface1)
+#
+ LoadConstantToReg (0x00025156,r0) @ldr r0, = 0x00025156
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000004 = Memory reads are synchronous
+ # 0x00000040 = Memory writes are synchronous
+ LoadConstantToReg (0x00000046,r0) @ldr r0, = 0x00000046
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ # 0x03800000 = ChipSelect3-Interface 1
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x03C00000,r0) @ldr r0, = 0x03C00000
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+ bx lr
+
+// IN r1 SmcBase
+// IN r2 VideoSRamBase
+// NOTE: This code is been called before any stack has been setup. It means some registers
+// could be overwritten (case of 'r0')
+ASM_PFX(SMCInitializeVRAM):
+#
+# Setup VRAM (CS1-Interface0)
+#
+ LoadConstantToReg (0x00049249,r0) @ldr r0, = 0x00049249
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ # 0x00000002 = MemoryWidth: 32bit
+ # 0x00000004 = Memory reads are synchronous
+ # 0x00000040 = Memory writes are synchronous
+ LoadConstantToReg (0x00000046,r0) @ldr r0, = 0x00000046
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ # 0x00800000 = ChipSelect1-Interface 0
+ # 0x00400000 = CmdTypes: UpdateRegs
+ LoadConstantToReg (0x00C00000,r0) @ldr r0, = 0x00C00000
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+#
+# Page mode setup for VRAM
+#
+ #read current state
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ LoadConstantToReg (0x00000000,r0) @ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ #enable page mode
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ LoadConstantToReg (0x00000000,r0) @ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ LoadConstantToReg (0x00900090,r0) @ldr r0, = 0x00900090
+ str r0, [r2, #0]
+
+ #confirm page mode enabled
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ LoadConstantToReg (0x00000000,r0) @ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ bx lr
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED \ No newline at end of file
diff --git a/ArmPlatformPkg/Drivers/PL35xSmc/InitializeSMC.asm b/ArmPlatformPkg/Drivers/PL35xSmc/InitializeSMC.asm
new file mode 100755
index 0000000000..732500e13a
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL35xSmc/InitializeSMC.asm
@@ -0,0 +1,153 @@
+//
+// Copyright (c) 2011, ARM Limited. All rights reserved.
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+//
+
+#include <AsmMacroIoLib.h>
+#include <Library/PcdLib.h>
+#include <Drivers/PL35xSmc.h>
+#include <AutoGen.h>
+
+ INCLUDE AsmMacroIoLib.inc
+
+ EXPORT SMCInitializeNOR
+ EXPORT SMCInitializeSRAM
+ EXPORT SMCInitializePeripherals
+ EXPORT SMCInitializeVRAM
+
+ PRESERVE8
+ AREA ModuleInitializeSMC, CODE, READONLY
+
+// CS0 CS0-Interf0 NOR1 flash on the motherboard
+// CS1 CS1-Interf0 Reserved for the motherboard
+// CS2 CS2-Interf0 SRAM on the motherboard
+// CS3 CS3-Interf0 memory-mapped Ethernet and USB controllers on the motherboard
+// CS4 CS0-Interf1 NOR2 flash on the motherboard
+// CS5 CS1-Interf1 memory-mapped peripherals
+// CS6 CS2-Interf1 memory-mapped peripherals
+// CS7 CS3-Interf1 system memory-mapped peripherals on the motherboard.
+
+// IN r1 SmcBase
+// IN r2 ChipSelect
+// NOTE: This code is been called before any stack has been setup. It means some registers
+// could be overwritten (case of 'r0')
+SMCInitializeNOR
+ // Write to set_cycle register(holding register for NOR 1 cycle register or NAND cycle register)
+ // - Read cycle timeout = 0xA (0:3)
+ // - Write cycle timeout = 0x3(7:4)
+ // - OE Assertion Delay = 0x9(11:8)
+ // - WE Assertion delay = 0x3(15:12)
+ // - Page cycle timeout = 0x2(19:16)
+ ldr r0, = 0x0002393A
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ // Write to set_opmode register(holding register for NOR 1 opomode register or NAND opmode register)
+ ldr r0, = (PL354_SMC_SET_OPMODE_MEM_WIDTH_32 :OR: PL354_SMC_SET_OPMODE_SET_RD_BURST_LENGTH_CONT :OR: PL354_SMC_SET_OPMODE_SET_WR_BURST_LENGTH_CONT :OR: PL354_SMC_SET_OPMODE_SET_ADV)
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ // Write to direct_cmd register so that the NOR 1 registers(set-cycles and opmode) are updated with holding registers
+ ldr r0, =PL354_SMC_DIRECT_CMD_ADDR_CMD_UPDATE
+ orr r0, r0, r2
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+ bx lr
+
+
+//
+// Setup SRAM (CS2-Interface0)
+//
+SMCInitializeSRAM
+ ldr r0, = 0x00027158
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ ldr r0, =(PL354_SMC_SET_OPMODE_MEM_WIDTH_32 :OR: PL354_SMC_SET_OPMODE_SET_ADV)
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ ldr r0, =(PL354_SMC_DIRECT_CMD_ADDR_CMD_UPDATE :OR: PL354_SMC_DIRECT_CMD_ADDR_CS(0,2))
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+ bx lr
+
+SMCInitializePeripherals
+//
+// USB/Eth/VRAM (CS3-Interface0)
+//
+ ldr r0, = 0x000CD2AA
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ ldr r0, =(PL354_SMC_SET_OPMODE_MEM_WIDTH_32 :OR: PL354_SMC_SET_OPMODE_SET_RD_SYNC :OR: PL354_SMC_SET_OPMODE_SET_WR_SYNC)
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ ldr r0, =(PL354_SMC_DIRECT_CMD_ADDR_CMD_UPDATE :OR: PL354_SMC_DIRECT_CMD_ADDR_CS(0,3))
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+
+//
+// Setup Peripherals (CS3-Interface1)
+//
+ ldr r0, = 0x00025156
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ ldr r0, =(PL354_SMC_SET_OPMODE_MEM_WIDTH_32 :OR: PL354_SMC_SET_OPMODE_SET_RD_SYNC :OR: PL354_SMC_SET_OPMODE_SET_WR_SYNC)
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ ldr r0, =(PL354_SMC_DIRECT_CMD_ADDR_CMD_UPDATE :OR: PL354_SMC_DIRECT_CMD_ADDR_CS(1,3))
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+ bx lr
+
+
+// IN r1 SmcBase
+// IN r2 VideoSRamBase
+// NOTE: This code is been called before any stack has been setup. It means some registers
+// could be overwritten (case of 'r0')
+SMCInitializeVRAM
+ //
+ // Setup VRAM (CS1-Interface0)
+ //
+ ldr r0, = 0x00049249
+ str r0, [r1, #PL354_SMC_SET_CYCLES_OFFSET]
+
+ ldr r0, = (PL354_SMC_SET_OPMODE_MEM_WIDTH_32 :OR: PL354_SMC_SET_OPMODE_SET_RD_SYNC :OR: PL354_SMC_SET_OPMODE_SET_WR_SYNC)
+ str r0, [r1, #PL354_SMC_SET_OPMODE_OFFSET]
+
+ ldr r0, = (PL354_SMC_DIRECT_CMD_ADDR_CMD_UPDATE :OR: PL354_SMC_DIRECT_CMD_ADDR_CS(0,1))
+ str r0, [r1, #PL354_SMC_DIRECT_CMD_OFFSET]
+
+ //
+ // Page mode setup for VRAM
+ //
+
+ // Read current state
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ // Enable page mode
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, = 0x00900090
+ str r0, [r2, #0]
+
+ // Confirm page mode enabled
+ ldr r0, [r2, #0]
+ ldr r0, [r2, #0]
+ ldr r0, = 0x00000000
+ str r0, [r2, #0]
+ ldr r0, [r2, #0]
+
+ bx lr
+
+ END
diff --git a/ArmPlatformPkg/Drivers/PL35xSmc/PL35xSmc.inf b/ArmPlatformPkg/Drivers/PL35xSmc/PL35xSmc.inf
new file mode 100755
index 0000000000..3960d49756
--- /dev/null
+++ b/ArmPlatformPkg/Drivers/PL35xSmc/PL35xSmc.inf
@@ -0,0 +1,29 @@
+#/* @file
+# Copyright (c) 2011, ARM Limited. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#*/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PL35xSmc
+ FILE_GUID = 10952220-aa32-11df-a438-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PL35xSmcLib
+
+[Sources.common]
+ InitializeSMC.asm | RVCT
+ InitializeSMC.S | GCC
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec