summaryrefslogtreecommitdiff
path: root/SamsungPlatformPkg/ExynosPkg/Exynos5250
diff options
context:
space:
mode:
Diffstat (limited to 'SamsungPlatformPkg/ExynosPkg/Exynos5250')
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.c692
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.h277
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.inf65
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.c788
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.h612
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.inf59
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390Gic.c70
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.c415
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.inf54
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicLib.inf28
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicNonSec.c44
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSec.c119
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSecLib.inf37
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.c177
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.inf46
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.c241
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.h417
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.inf57
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/ComponentName.c231
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/ComponentName.h145
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/Ohci.c2345
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/Ohci.h229
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDebug.c181
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDebug.h51
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDxe.inf88
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciQueue.c993
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciQueue.h395
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciReg.c292
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciReg.h286
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciSched.c1254
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciSched.h270
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/UsbHcMem.c564
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/UsbHcMem.h161
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB.c353
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB2Phy.h114
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB3Drd.h403
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB3Phy.h80
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.c684
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.h290
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf64
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciRootBridgeIo.c306
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.c120
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.h40
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.inf49
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.c1348
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.h259
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.inf58
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_5250.c658
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_5250.h323
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_CMD.h165
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.c469
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.inf54
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c1378
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.h308
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.inf64
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_5250.c721
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_5250.h322
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_CMD.h165
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMC_Fvb.c587
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec101
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/ExynosLib.h42
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/ExynosTimerLib.h56
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/MpParkLib.h51
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/com_dtypes.h186
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/ArmPlatform.h692
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Arndale5250.h337
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Arndale5250_Val.h402
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Exynos5250.h730
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Exynos5250_Evt1.h763
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Protocol/ExynosGpio.h199
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Protocol/ExynosRng.h52
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.c51
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.inf42
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/GdbSerialLib/GdbSerialLib.c118
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/GdbSerialLib/GdbSerialLib.inf40
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/RealTimeClockLib/RealTimeClockLib.c363
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/RealTimeClockLib/RealTimeClockLib.inf42
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ResetSystemLib/ResetSystemLib.c241
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ResetSystemLib/ResetSystemLib.inf52
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Library/SerialPortLib/SerialPortLib_Evt1.c159
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/Library/SerialPortLib/SerialPortLib_Evt1.inf38
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/TimerLib/TimerLib.c287
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/TimerLib/TimerLib.inf41
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeiLib.c182
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeiLib.inf69
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.c157
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.inf75
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeiLib.c30
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeiLib.inf53
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.c138
-rwxr-xr-xSamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.inf69
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Helper.S84
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Helper.asm75
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.c222
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.inf85
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecEntryPoint.S287
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecEntryPoint.asm112
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecFromTzsw.S13
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecInternal.h75
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Smc.c110
-rw-r--r--SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Smc.h60
101 files changed, 28046 insertions, 0 deletions
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.c
new file mode 100644
index 000000000..d1b5a3be6
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.c
@@ -0,0 +1,692 @@
+/** @file
+ Template for Timer Architecture Protocol driver of the ARM flavor
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/ExynosGpio.h>
+#include <Platform/ArmPlatform.h>
+#include <Platform/Exynos5250.h>
+#include "DisplayDxe.h"
+
+
+typedef struct {
+ VENDOR_DEVICE_PATH DisplayDevicePath;
+ EFI_DEVICE_PATH EndDevicePath;
+} DISPLAY_DEVICE_PATH;
+
+DISPLAY_DEVICE_PATH gDisplayDevicePath =
+{
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0
+ }
+};
+
+#define LCD_WIDTH 1280
+#define LCD_HEIGHT 800
+
+#define VCLK 62946240
+
+#define SRC_CLK 800000000
+
+/**
+ This function configures the MIPI-DSIM channel
+**/
+INT32 s5p_mipi_dsi_wr_data(UINT32 data_id, UINT32 data0, UINT32 data1)
+{
+ UINT32 DSIM1BaseAddr = PcdGet32(PcdDSIM1Base);
+ UINT32 data_cnt = 0;
+ UINT32 payload = 0;
+ UINT32 timeout_count = 100000;
+
+ MicroSecondDelay(20000);
+
+ /* in case that data count is more then 4 */
+ for (data_cnt=0; data_cnt<data1; data_cnt+=4) {
+ /*
+ * after sending 4bytes per one time,
+ * send remainder data less then 4.
+ */
+ if ((data1 - data_cnt) < 4) {
+ if ((data1 - data_cnt) == 3) {
+ payload = *(UINT8 *)(data0 + data_cnt) | (*(UINT8 *)(data0 + (data_cnt + 1))) << 8 | (*(UINT8 *)(data0 + (data_cnt + 2))) << 16;
+ } else if ((data1 - data_cnt) == 2) {
+ payload = *(UINT8 *)(data0 + data_cnt) | (*(UINT8 *)(data0 + (data_cnt + 1))) << 8;
+ } else if ((data1 - data_cnt) == 1) {
+ payload = *(UINT8 *)(data0 + data_cnt);
+ }
+
+ MmioWrite32(DSIM1BaseAddr + DSIM_PAYLOAD, payload);
+ /* send 4bytes per one time. */
+ } else {
+ payload = *(UINT8 *)(data0 + data_cnt) | (*(UINT8 *)(data0 + (data_cnt + 1))) << 8 | \
+ (*(UINT8 *)(data0 + (data_cnt + 2))) << 16 | (*(UINT8 *)(data0 + (data_cnt + 3))) << 24;
+
+ MmioWrite32(DSIM1BaseAddr + DSIM_PAYLOAD, payload);
+ }
+ }
+
+ MmioWrite32(DSIM1BaseAddr + DSIM_PKTHDR, ((((data1 & 0xFF00) >> 8)<<16) | ((data1 & 0xFF)<<8) | ((data_id & 0x3F)<<0)));
+
+ while(1) {
+ if(timeout_count == 0)
+ return -1;
+
+ if(MmioRead32(DSIM1BaseAddr + DSIM_INTSRC) & (0x1<<29)) {
+ MmioWrite32(DSIM1BaseAddr + DSIM_INTSRC, (0x1<<29));
+ return 1;
+ }
+ else if((MmioRead32(DSIM1BaseAddr + DSIM_FIFOCTRL) & 0xF00000) == 0)
+ return -1;
+ timeout_count--;
+ }
+}
+
+INT32 lcd_display_on(VOID)
+{
+ UINT8 initcode_013c[6] = {0x3c, 0x01, 0x03, 0x00, 0x02, 0x00};
+ UINT8 initcode_0114[6] = {0x14, 0x01, 0x02, 0x00, 0x00, 0x00};
+ UINT8 initcode_0164[6] = {0x64, 0x01, 0x05, 0x00, 0x00, 0x00};
+ UINT8 initcode_0168[6] = {0x68, 0x01, 0x05, 0x00, 0x00, 0x00};
+ UINT8 initcode_016c[6] = {0x6c, 0x01, 0x05, 0x00, 0x00, 0x00};
+ UINT8 initcode_0170[6] = {0x70, 0x01, 0x05, 0x00, 0x00, 0x00};
+ UINT8 initcode_0134[6] = {0x34, 0x01, 0x1f, 0x00, 0x00, 0x00};
+ UINT8 initcode_0210[6] = {0x10, 0x02, 0x1f, 0x00, 0x00, 0x00};
+ UINT8 initcode_0104[6] = {0x04, 0x01, 0x01, 0x00, 0x00, 0x00};
+ UINT8 initcode_0204[6] = {0x04, 0x02, 0x01, 0x00, 0x00, 0x00};
+ UINT8 initcode_0450[6] = {0x50, 0x04, 0x20, 0x01, 0xfa, 0x00};
+ UINT8 initcode_0454[6] = {0x54, 0x04, 0x20, 0x00, 0x50, 0x00};
+ UINT8 initcode_0458[6] = {0x58, 0x04, 0x00, 0x05, 0x30, 0x00};
+ UINT8 initcode_045c[6] = {0x5c, 0x04, 0x05, 0x00, 0x0a, 0x00};
+ UINT8 initcode_0460[6] = {0x60, 0x04, 0x20, 0x03, 0x0a, 0x00};
+ UINT8 initcode_0464[6] = {0x64, 0x04, 0x01, 0x00, 0x00, 0x00};
+ UINT8 initcode_04a0_1[6] = {0xa0, 0x04, 0x06, 0x80, 0x44, 0x00};
+ UINT8 initcode_04a0_2[6] = {0xa0, 0x04, 0x06, 0x80, 0x04, 0x00};
+ UINT8 initcode_0504[6] = {0x04, 0x05, 0x04, 0x00, 0x00, 0x00};
+ UINT8 initcode_049c[6] = {0x9c, 0x04, 0x0d, 0x00, 0x00, 0x00};
+
+ /* Initialize MIPI LCD */
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_013c, sizeof(initcode_013c)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0114, sizeof(initcode_0114)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0164, sizeof(initcode_0164)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0168, sizeof(initcode_0168)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_016c, sizeof(initcode_016c)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0170, sizeof(initcode_0170)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0134, sizeof(initcode_0134)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0210, sizeof(initcode_0210)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0104, sizeof(initcode_0104)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0204, sizeof(initcode_0204)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0450, sizeof(initcode_0450)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0454, sizeof(initcode_0454)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0458, sizeof(initcode_0458)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_045c, sizeof(initcode_045c)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0460, sizeof(initcode_0460)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0464, sizeof(initcode_0464)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_04a0_1, sizeof(initcode_04a0_1)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_04a0_2, sizeof(initcode_04a0_2)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_0504, sizeof(initcode_0504)) == -1)
+ return 0;
+ MicroSecondDelay(6000);
+ if(s5p_mipi_dsi_wr_data(0x29, (UINT32)initcode_049c, sizeof(initcode_049c)) == -1)
+ return 0;
+ MicroSecondDelay(800000);
+
+ return 1;
+}
+
+VOID ConfigureMIPI(VOID)
+{
+ UINT32 DSIM1BaseAddr = PcdGet32(PcdDSIM1Base);
+ UINT32 DSIM_status;
+ BOOLEAN config_done = FALSE;
+
+ /* Enable MIPI-DSIM clock */
+ MmioAndThenOr32((PcdGet32(PcdCmuBase) + CLK_GATE_IP_DISP1_OFFSET), ~CLK_GATE_DSIM1_MASK,CLK_GATE_DSIM1_MASK);
+
+ while(!config_done) {
+ /* Enable MIPI PHY1 */
+ MmioAndThenOr32((PcdGet32(PcdPmuBase) +PMU_MIPI_PHY1_CONTROL_OFFSET), ~(1<<0), (1<<0));
+ /* Reset DSIM part of MIPI PHY1 */
+ MmioAndThenOr32((PcdGet32(PcdPmuBase) +PMU_MIPI_PHY1_CONTROL_OFFSET), ~(1<<2), (1<<2));
+
+ /* DSIM SW Reset */
+ MmioOr32(DSIM1BaseAddr + DSIM_SWRST, (1<<0));
+
+ /* Disable swap of Dp/Dn channel of data and clock lanes */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_PHYACCHR1, ~(0x3<<0), ((0 & 0x3)<<0));
+
+ /* DSIM SW Reset */
+ MmioOr32(DSIM1BaseAddr + DSIM_SWRST, (1<<0));
+
+ /* Initialize FIFO pointer */
+ MmioAnd32(DSIM1BaseAddr + DSIM_FIFOCTRL, ~(0x1F<<0));
+ MicroSecondDelay(10000);
+ MmioOr32(DSIM1BaseAddr + DSIM_FIFOCTRL, (0x1F<<0));
+
+ /* DSI configuration */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_CONFIG, ~((0x1<<28) | (0x1F<<20) | (0x3<<5)), (0x3<<5));
+ MmioOr32(DSIM1BaseAddr + DSIM_CONFIG, ((0x1<<0)|(0x1<<1)|(0x1<<2)|(0x1<<3)|(0x1<<4)));
+
+ /* clock configuration */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_CLKCTRL, ~(0x3<<25), (0x0<<25));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_PHYACCHR, ~(0x7<<5), ((0x1<<14)|(0x3<<5)));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_PLLCTRL, ~(0x7FFFF<<1), ((3<<13)|(115<<4)|(1<<1)));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_PLLCTRL, ~(0xF<<28), (0x0<<28));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_PLLCTRL, ~(0x7<<20), (0x0<<20));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_PLLCTRL, ~(0xF<<24), (0x8<<24));
+ MmioWrite32(DSIM1BaseAddr + DSIM_PLLTMR, 500);
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_CLKCTRL, ~(0x1<<27), (0x0<<27));
+
+ /* Enable PLL */
+ MmioWrite32(DSIM1BaseAddr + DSIM_INTSRC, (0x1<<31));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_PLLCTRL, ~(0x1<<23), (0x1<<23));
+ while(1) {
+ if(MmioRead32(DSIM1BaseAddr + DSIM_STATUS) & (0x1<<31))
+ break;
+ }
+
+ /* Enable byte clock */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_CLKCTRL, ~(0x1<<24), (0x1<<24));
+ /* Enable escape clock */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_CLKCTRL, ~((0x1<<28) | (0xFFFF<<0)), ((0x1<<28) | (144<<0)));
+ /* Enable escape clock data and clock lanes */
+ MmioOr32(DSIM1BaseAddr + DSIM_CLKCTRL, (0x1F<<19));
+
+ MicroSecondDelay(100000);
+
+ while(1) {
+ DSIM_status = MmioRead32(DSIM1BaseAddr + DSIM_STATUS);
+ if((DSIM_status & (0xF<<0)) && ((DSIM_status & (0x1<<8)) || (DSIM_status & (0x1<<10))))
+ break;
+ }
+
+ /* BTA sequence counters */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_ESCMODE, ~(0x7FF<<21), ((0xF &0x7FF) << 21));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_TIMEOUT, ~(0xFF<<16), (0xFF<<16));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_TIMEOUT, ~(0xFFFF<<0), (0xFFFF<<0));
+
+ /* Enable HS clock */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_CLKCTRL, ~(0x1<<31), (0x1<<31));
+
+ /* Set CPU transfer mode */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_ESCMODE, ~(0x1<<7), (0x1<<7));
+
+ /* Set display mode */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_MVPORCH, ~((0xF<<28)|(0x7FF<<16)|(0x7FF<<0)), ((0xF<<28)|(0x4<<16)|(0x4<<0)));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_MHPORCH, ~((0xFFFF<<16)|(0xFFFF<<0)), ((0x4<<16)|(0x4<<0)));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_MSYNC, ~((0x3FF<<22)|(0xFFFF<<0)), ((0x4<<22)|(0x4<<0)));
+
+ MmioAnd32(DSIM1BaseAddr + DSIM_MDRESOL, ~(0x1<<31));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_MDRESOL, ~((0x7FF<<16)|(0x7FF<<0)), ((0x1<<31)|(LCD_HEIGHT<<16)|(LCD_WIDTH<<0)));
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_CONFIG, ~((0x3<<26)|(0x1<<25)|(0x3<<18)|(0x7<<12)|(0x3<<16)|(0x7<<8)), \
+ ((0x1<<26)|(0x1<<25)|(0x7<<12)));
+
+ /* Clear interrupt status */
+ MmioWrite32(DSIM1BaseAddr + DSIM_INTSRC, (0x1<<29));
+
+ if(lcd_display_on() == 1)
+ config_done = TRUE;
+
+ /* Reset CPU transfer mode */
+ MmioAndThenOr32(DSIM1BaseAddr + DSIM_ESCMODE, ~(0x1<<7), (0x0<<7));
+
+ if(!config_done)
+ MmioOr32(DSIM1BaseAddr + DSIM_SWRST, (1<<0)); /* DSIM SW Reset */
+ }
+}
+
+VOID s5p_mipi_dsi_func_reset(VOID)
+{
+ UINT32 DSIM1BaseAddr = PcdGet32(PcdDSIM1Base);
+
+ MmioOr32(DSIM1BaseAddr + DSIM_SWRST, (1<<16));
+}
+
+/**
+ This function configures the Power Domain of the LCD 0 Module to Normal Mode.
+**/
+VOID ConfigurePower(VOID)
+{
+ UINT32 PrevGateState;
+
+ /* Enable FIMD1 power domain */
+ PrevGateState = MmioRead32((PcdGet32(PcdCmuBase) + CLK_GATE_IP_DISP1_OFFSET));
+ MmioWrite32((PcdGet32(PcdCmuBase) + CLK_GATE_IP_DISP1_OFFSET), 0xFFFFFFFF);
+
+ MmioWrite32((PcdGet32(PcdPmuBase) + PMU_DISP1_CONFIGURATION_OFFSET), LOCAL_PWR_ENABLE);
+ while( (MmioRead32((PcdGet32(PcdPmuBase) + PMU_DISP1_STATUS_OFFSET)) & LOCAL_PWR_ENABLE) != \
+ LOCAL_PWR_ENABLE);
+
+ MmioWrite32((PcdGet32(PcdCmuBase) + CLK_GATE_IP_DISP1_OFFSET), PrevGateState);
+}
+
+/**
+ This function configures Clock Source,Clock gating,Clock Divider and Mask values for the
+ FIMD0 in the LCD0 Module
+
+**/
+VOID ConfigureClk(VOID)
+{
+ MmioAndThenOr32((PcdGet32(PcdCmuBase) + CLK_GATE_IP_DISP1_OFFSET), \
+ ~CLK_GATE_FIMD1_MASK,CLK_GATE_FIMD1_MASK);
+
+ /* MPLL is the clock source of FIMD1 IP */
+ MmioAndThenOr32((PcdGet32(PcdCmuBase) + CLK_SRC_DISP1_0_OFFSET), \
+ ~CLK_SRC_FIMD1_MASK, CLK_SRC_FIMD1_SEL(FIMD1_SCLKMPLL));
+
+ /* Considering MPLL=800000000(800 MHz), SCLK_FIMD0=800000000(800 MHz) => DIV => (800/800) => 1
+ The DIV value to be programmed should be (1 -1) = 0 */
+ MmioAndThenOr32((PcdGet32(PcdCmuBase) + CLK_DIV_DISP1_0_OFFSET), \
+ ~CLK_DIV_FIMD1_MASK, CLK_DIV_FIMD1_SEL(FIMD1_CLK_DIV));
+
+ MmioOr32((PcdGet32(PcdCmuBase) + CLK_SRC_MASK_DISP1_0_OFFSET), CLK_SRC_DISP1_0_UNMASK);
+}
+
+VOID lcd_power_on(VOID)
+{
+ EFI_STATUS Status;
+ EXYNOS_GPIO *Gpio;
+
+ Status = gBS->LocateProtocol(&gSamsungPlatformGpioProtocolGuid, NULL, (VOID **)&Gpio);
+ ASSERT_EFI_ERROR(Status);
+
+ /* reset */
+ Gpio->Set(Gpio,LCD_RESET,GPIO_MODE_OUTPUT_1);
+ MicroSecondDelay(20000);
+ Gpio->Set(Gpio,LCD_RESET,GPIO_MODE_OUTPUT_0);
+ MicroSecondDelay(20000);
+ Gpio->Set(Gpio,LCD_RESET,GPIO_MODE_OUTPUT_1);
+ MicroSecondDelay(20000);
+
+ /* power */
+ Gpio->Set(Gpio,LCD_POWER,GPIO_MODE_OUTPUT_0);
+ MicroSecondDelay(20000);
+ Gpio->Set(Gpio,LCD_POWER,GPIO_MODE_OUTPUT_1);
+ MicroSecondDelay(20000);
+
+ /*backlight */
+ Gpio->Set(Gpio,LCD_BACKLIGHT,GPIO_MODE_OUTPUT_0);
+ MicroSecondDelay(20000);
+ Gpio->Set(Gpio,LCD_BACKLIGHT,GPIO_MODE_OUTPUT_1);
+ MicroSecondDelay(20000);
+}
+
+
+VOID LCD_Initialize(VOID)
+{
+ UINTN div;
+ UINT32 Fimd1BaseAddr = PcdGet32(PcdFIMD1Base);
+ UINT32 FBAddr = PcdGet32(PcdFrameBufferBase);
+
+ gBS->SetMem((VOID *)FBAddr, (LCD_WIDTH*LCD_HEIGHT*4), 0x0);
+
+ ConfigurePower();
+
+ /* Power up the LCD */
+ lcd_power_on();
+
+ /* Initialize MIPI-DSIM */
+ ConfigureMIPI();
+
+ ConfigureClk();
+
+ /* Set FIMD1 bypass */
+ MmioOr32((PcdGet32(PcdSysBase) + SYS_DISP1BLK_CFG_OFFSET), FIMDBYPASS_DISP1);
+
+ /* Configure FIMD */
+ MmioAndThenOr32(Fimd1BaseAddr + VIDCON1_OFFSET, ~S5P_VIDCON1_FIXVCLK_MASK, (S5P_VIDCON1_IVCLK_RISING_EDGE | \
+ S5P_VIDCON1_FIXVCLK_RUN));
+
+ MmioOr32(Fimd1BaseAddr + SHADOWCON_OFFSET, S5P_SHADOWCON_PROTECT(0));
+
+ div = SRC_CLK / VCLK;
+
+ MmioAndThenOr32(Fimd1BaseAddr + VIDCON0_OFFSET, ~S5P_VIDCON0_CLKVAL_F_MASK, (S5P_VIDCON0_CLKDIR_DIVIDED | \
+ S5P_VIDCON0_CLKVAL_F(div - 1) | S5P_VIDCON0_ENVID_ENABLE | S5P_VIDCON0_ENVID_F_ENABLE));
+ MmioOr32(Fimd1BaseAddr + VIDTCON0_OFFSET, (S5P_VIDTCON0_VBPD(3) | S5P_VIDTCON0_VFPD(3) | S5P_VIDTCON0_VSPW(3)));
+ MmioOr32(Fimd1BaseAddr + VIDTCON1_OFFSET, (S5P_VIDTCON1_HBPD(3) | S5P_VIDTCON1_HFPD(3) | S5P_VIDTCON1_HSPW(3)));
+
+ MmioOr32(Fimd1BaseAddr + VIDTCON2_OFFSET, (S5P_VIDTCON2_HOZVAL(LCD_WIDTH - 1) | S5P_VIDTCON2_LINEVAL(LCD_HEIGHT - 1)));
+
+ MmioWrite32(Fimd1BaseAddr + VIDADDR_START0_OFFSET(0), FBAddr);
+ MmioWrite32(Fimd1BaseAddr + VIDADDR_END0_OFFSET(0), (FBAddr + (LCD_WIDTH * LCD_HEIGHT * 4)));
+ MmioWrite32(Fimd1BaseAddr + VIDADDR_SIZE_OFFSET(0), (S5P_VIDADDR_PAGEWIDTH(LCD_WIDTH * 4) | S5P_VIDADDR_OFFSIZE(0)));
+
+ MmioWrite32(Fimd1BaseAddr + VIDOSD_A_OFFSET(0), (S5P_VIDOSD_LEFT_X(0) | S5P_VIDOSD_TOP_Y(0)));
+ MmioWrite32(Fimd1BaseAddr + VIDOSD_B_OFFSET(0), (S5P_VIDOSD_RIGHT_X(LCD_WIDTH - 1) | S5P_VIDOSD_BOTTOM_Y(LCD_HEIGHT - 1)));
+ MmioWrite32(Fimd1BaseAddr + VIDOSD_C_OFFSET(0), S5P_VIDOSD_SIZE(LCD_WIDTH * LCD_HEIGHT));
+
+ MmioOr32(Fimd1BaseAddr + SHADOWCON_OFFSET, S5P_SHADOWCON_CH_ENABLE(0));
+
+ MmioAndThenOr32(Fimd1BaseAddr + WINCON_OFFSET(0), ~(S5P_WINCON_BURSTLEN_MASK | S5P_WINCON_BPPMODE_MASK), \
+ (S5P_WINCON_WSWP_ENABLE | S5P_WINCON_BURSTLEN_16WORD | S5P_WINCON_BPPMODE_24BPP_888 | S5P_WINCON_ENWIN_ENABLE));
+
+ MmioAnd32(Fimd1BaseAddr + SHADOWCON_OFFSET, ~(S5P_SHADOWCON_PROTECT(0)));
+
+#if defined(LCD_MIPI_TC358764)
+ s5p_mipi_dsi_func_reset();
+#endif
+}
+
+EFI_STATUS
+EFIAPI
+DisplayQueryMode(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ );
+
+EFI_STATUS
+EFIAPI
+DisplaySetMode(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ );
+
+EFI_STATUS
+EFIAPI
+DisplayBlt(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ );
+
+EFI_GRAPHICS_OUTPUT_PROTOCOL gDisplay = {
+ DisplayQueryMode,
+ DisplaySetMode,
+ DisplayBlt,
+ NULL
+};
+
+
+EFI_STATUS
+EFIAPI
+DisplayQueryMode(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+ (VOID **)Info
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ *SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+ (*Info)->Version = This->Mode->Info->Version;
+ (*Info)->HorizontalResolution = This->Mode->Info->HorizontalResolution;
+ (*Info)->VerticalResolution = This->Mode->Info->VerticalResolution;
+ (*Info)->PixelFormat = This->Mode->Info->PixelFormat;
+ (*Info)->PixelsPerScanLine = This->Mode->Info->PixelsPerScanLine;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DisplaySetMode(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DisplayBlt(
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ )
+{
+ UINT8 *VidBuf, *BltBuf, *VidBuf1;
+ UINTN i, j;
+
+ switch(BltOperation) {
+ case EfiBltVideoFill:
+ BltBuf = (UINT8 *)BltBuffer;
+
+ for(i=0;i<Height;i++) {
+ VidBuf = (UINT8 *)((UINT32)This->Mode->FrameBufferBase + \
+ (DestinationY + i)*This->Mode->Info->PixelsPerScanLine*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + \
+ DestinationX*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ for(j=0;j<Width;j++) {
+ gBS->CopyMem((VOID *)VidBuf, (VOID *)BltBuf, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ VidBuf += sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ }
+ }
+ break;
+
+ case EfiBltVideoToBltBuffer:
+ if(Delta == 0)
+ Delta = Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+
+ for(i=0;i<Height;i++) {
+ VidBuf = (UINT8 *)((UINT32)This->Mode->FrameBufferBase + \
+ (SourceY + i)*This->Mode->Info->PixelsPerScanLine*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + \
+ SourceX*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ BltBuf = (UINT8 *)((UINT32)BltBuffer + (DestinationY + i)*Delta + DestinationX*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ for(j=0;j<Width;j++) {
+ gBS->CopyMem((VOID *)BltBuf, (VOID *)VidBuf, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ VidBuf += sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuf += sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ }
+ }
+ break;
+
+ case EfiBltBufferToVideo:
+ if(Delta == 0)
+ Delta = Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+
+ for(i=0;i<Height;i++) {
+ VidBuf = (UINT8 *)((UINT32)This->Mode->FrameBufferBase + \
+ (DestinationY + i)*This->Mode->Info->PixelsPerScanLine*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + \
+ DestinationX*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ BltBuf = (UINT8 *)((UINT32)BltBuffer + (SourceY + i)*Delta + SourceX*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ for(j=0;j<Width;j++) {
+ gBS->CopyMem((VOID *)VidBuf, (VOID *)BltBuf, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ VidBuf += sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ BltBuf += sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ }
+ }
+ break;
+
+ case EfiBltVideoToVideo:
+ for(i=0;i<Height;i++) {
+ VidBuf = (UINT8 *)((UINT32)This->Mode->FrameBufferBase + \
+ (SourceY + i)*This->Mode->Info->PixelsPerScanLine*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + \
+ SourceX*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ VidBuf1 = (UINT8 *)((UINT32)This->Mode->FrameBufferBase + \
+ (DestinationY + i)*This->Mode->Info->PixelsPerScanLine*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + \
+ DestinationX*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+
+ for(j=0;j<Width;j++) {
+ gBS->CopyMem((VOID *)VidBuf1, (VOID *)VidBuf, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ VidBuf += sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ VidBuf1 += sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
+ }
+ }
+ break;
+
+ default:
+ ASSERT_EFI_ERROR(EFI_SUCCESS);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Initialize the state information for the Display Dxe
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+DisplayDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+ EFI_GUID DevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+ UINT32 FBAddr = PcdGet32(PcdFrameBufferBase);
+
+ /* Initialize Display */
+ LCD_Initialize();
+ if(gDisplay.Mode == NULL){
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),
+ (VOID **)&gDisplay.Mode
+ );
+ ASSERT_EFI_ERROR(Status);
+ ZeroMem(gDisplay.Mode,sizeof(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
+ }
+ if(gDisplay.Mode->Info==NULL){
+ Status = gBS->AllocatePool(
+ EfiBootServicesData,
+ sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
+ (VOID **)&gDisplay.Mode->Info
+ );
+ ASSERT_EFI_ERROR(Status);
+ ZeroMem(gDisplay.Mode->Info,sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+ }
+ /* Fill out mode information */
+ gDisplay.Mode->MaxMode = 1;
+ gDisplay.Mode->Mode = 0;
+ gDisplay.Mode->Info->Version = 0;
+ gDisplay.Mode->Info->HorizontalResolution = LCD_WIDTH;
+ gDisplay.Mode->Info->VerticalResolution = LCD_HEIGHT;
+ gDisplay.Mode->Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+ gDisplay.Mode->Info->PixelsPerScanLine = LCD_WIDTH;
+ gDisplay.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+ gDisplay.Mode->FrameBufferBase = FBAddr;
+ gDisplay.Mode->FrameBufferSize = (LCD_WIDTH * LCD_HEIGHT * 4);
+
+#if 0
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &DevicePathProtocolGuid,
+ &gDisplayDevicePath,
+ &GraphicsOutputProtocolGuid,
+ &gDisplay,
+ NULL);
+#else
+ {
+ EFI_HANDLE gUEFIDisplayHandle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gUEFIDisplayHandle,
+ &DevicePathProtocolGuid,
+ &gDisplayDevicePath,
+ &GraphicsOutputProtocolGuid,
+ &gDisplay,
+ NULL);
+
+ }
+#endif
+
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.h
new file mode 100644
index 000000000..5b784f384
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.h
@@ -0,0 +1,277 @@
+/** @file
+*
+* Copyright (c) 2012, Samsung Electronics Co. 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 _DisplayDxe_H__
+#define _DisplayDxe_H__
+
+/*
+ * Bit Definitions
+*/
+
+/* VIDCON0 */
+#define S5P_VIDCON0_DSI_DISABLE (0 << 30)
+#define S5P_VIDCON0_DSI_ENABLE (1 << 30)
+#define S5P_VIDCON0_SCAN_PROGRESSIVE (0 << 29)
+#define S5P_VIDCON0_SCAN_INTERLACE (1 << 29)
+#define S5P_VIDCON0_SCAN_MASK (1 << 29)
+#define S5P_VIDCON0_VIDOUT_RGB (0 << 26)
+#define S5P_VIDCON0_VIDOUT_ITU (1 << 26)
+#define S5P_VIDCON0_VIDOUT_I80LDI0 (2 << 26)
+#define S5P_VIDCON0_VIDOUT_I80LDI1 (3 << 26)
+#define S5P_VIDCON0_VIDOUT_WB_RGB (4 << 26)
+#define S5P_VIDCON0_VIDOUT_WB_I80LDI0 (6 << 26)
+#define S5P_VIDCON0_VIDOUT_WB_I80LDI1 (7 << 26)
+#define S5P_VIDCON0_VIDOUT_MASK (7 << 26)
+#define S5P_VIDCON0_PNRMODE_RGB_P (0 << 17)
+#define S5P_VIDCON0_PNRMODE_BGR_P (1 << 17)
+#define S5P_VIDCON0_PNRMODE_RGB_S (2 << 17)
+#define S5P_VIDCON0_PNRMODE_BGR_S (3 << 17)
+#define S5P_VIDCON0_PNRMODE_MASK (3 << 17)
+#define S5P_VIDCON0_PNRMODE_SHIFT (17)
+#define S5P_VIDCON0_CLKVALUP_ALWAYS (0 << 16)
+#define S5P_VIDCON0_CLKVALUP_START_FRAME (1 << 16)
+#define S5P_VIDCON0_CLKVALUP_MASK (1 << 16)
+#define S5P_VIDCON0_CLKVAL_F(x) (((x) & 0xff) << 6)
+#define S5P_VIDCON0_CLKVAL_F_MASK (0xff << 6)
+#define S5P_VIDCON0_VCLKEN_NORMAL (0 << 5)
+#define S5P_VIDCON0_VCLKEN_FREERUN (1 << 5)
+#define S5P_VIDCON0_VCLKEN_MASK (1 << 5)
+#define S5P_VIDCON0_CLKDIR_DIRECTED (0 << 4)
+#define S5P_VIDCON0_CLKDIR_DIVIDED (1 << 4)
+#define S5P_VIDCON0_CLKDIR_MASK (1 << 4)
+#define S5P_VIDCON0_CLKSEL_HCLK (0 << 2)
+#define S5P_VIDCON0_CLKSEL_SCLK (1 << 2)
+#define S5P_VIDCON0_CLKSEL_MASK (1 << 2)
+#define S5P_VIDCON0_ENVID_ENABLE (1 << 1)
+#define S5P_VIDCON0_ENVID_DISABLE (0 << 1)
+#define S5P_VIDCON0_ENVID_F_ENABLE (1 << 0)
+#define S5P_VIDCON0_ENVID_F_DISABLE (0 << 0)
+
+/* VIDCON1 */
+#define S5P_VIDCON1_FIXVCLK_MASK (3 << 9)
+#define S5P_VIDCON1_FIXVCLK_HOLD (0 << 9)
+#define S5P_VIDCON1_FIXVCLK_RUN (1 << 9)
+#define S5P_VIDCON1_IVCLK_FALLING_EDGE (0 << 7)
+#define S5P_VIDCON1_IVCLK_RISING_EDGE (1 << 7)
+#define S5P_VIDCON1_IHSYNC_NORMAL (0 << 6)
+#define S5P_VIDCON1_IHSYNC_INVERT (1 << 6)
+#define S5P_VIDCON1_IVSYNC_NORMAL (0 << 5)
+#define S5P_VIDCON1_IVSYNC_INVERT (1 << 5)
+#define S5P_VIDCON1_IVDEN_NORMAL (0 << 4)
+#define S5P_VIDCON1_IVDEN_INVERT (1 << 4)
+
+/* VIDCON2 */
+#define S5P_VIDCON2_EN601_DISABLE (0 << 23)
+#define S5P_VIDCON2_EN601_ENABLE (1 << 23)
+#define S5P_VIDCON2_EN601_MASK (1 << 23)
+#define S5P_VIDCON2_WB_DISABLE (0 << 15)
+#define S5P_VIDCON2_WB_ENABLE (1 << 15)
+#define S5P_VIDCON2_WB_MASK (1 << 15)
+#define S5P_VIDCON2_TVFORMATSEL_HW (0 << 14)
+#define S5P_VIDCON2_TVFORMATSEL_SW (1 << 14)
+#define S5P_VIDCON2_TVFORMATSEL_MASK (1 << 14)
+#define S5P_VIDCON2_TVFORMATSEL_YUV422 (1 << 12)
+#define S5P_VIDCON2_TVFORMATSEL_YUV444 (2 << 12)
+#define S5P_VIDCON2_TVFORMATSEL_YUV_MASK (3 << 12)
+#define S5P_VIDCON2_ORGYUV_YCBCR (0 << 8)
+#define S5P_VIDCON2_ORGYUV_CBCRY (1 << 8)
+#define S5P_VIDCON2_ORGYUV_MASK (1 << 8)
+#define S5P_VIDCON2_YUVORD_CBCR (0 << 7)
+#define S5P_VIDCON2_YUVORD_CRCB (1 << 7)
+#define S5P_VIDCON2_YUVORD_MASK (1 << 7)
+
+/* PRTCON */
+#define S5P_PRTCON_UPDATABLE (0 << 11)
+#define S5P_PRTCON_PROTECT (1 << 11)
+
+/* VIDTCON0 */
+#define S5P_VIDTCON0_VBPDE(x) (((x) & 0xff) << 24)
+#define S5P_VIDTCON0_VBPD(x) (((x) & 0xff) << 16)
+#define S5P_VIDTCON0_VFPD(x) (((x) & 0xff) << 8)
+#define S5P_VIDTCON0_VSPW(x) (((x) & 0xff) << 0)
+
+/* VIDTCON1 */
+#define S5P_VIDTCON1_VFPDE(x) (((x) & 0xff) << 24)
+#define S5P_VIDTCON1_HBPD(x) (((x) & 0xff) << 16)
+#define S5P_VIDTCON1_HFPD(x) (((x) & 0xff) << 8)
+#define S5P_VIDTCON1_HSPW(x) (((x) & 0xff) << 0)
+
+/* VIDTCON2 */
+#define S5P_VIDTCON2_LINEVAL(x) (((x) & 0x7ff) << 11)
+#define S5P_VIDTCON2_HOZVAL(x) (((x) & 0x7ff) << 0)
+
+/* Window 0~4 Control - WINCONx */
+#define S5P_WINCON_DATAPATH_DMA (0 << 22)
+#define S5P_WINCON_DATAPATH_LOCAL (1 << 22)
+#define S5P_WINCON_DATAPATH_MASK (1 << 22)
+#define S5P_WINCON_BUFSEL_0 (0 << 20)
+#define S5P_WINCON_BUFSEL_1 (1 << 20)
+#define S5P_WINCON_BUFSEL_MASK (1 << 20)
+#define S5P_WINCON_BUFSEL_SHIFT (20)
+#define S5P_WINCON_BUFAUTO_DISABLE (0 << 19)
+#define S5P_WINCON_BUFAUTO_ENABLE (1 << 19)
+#define S5P_WINCON_BUFAUTO_MASK (1 << 19)
+#define S5P_WINCON_BITSWP_DISABLE (0 << 18)
+#define S5P_WINCON_BITSWP_ENABLE (1 << 18)
+#define S5P_WINCON_BITSWP_SHIFT (18)
+#define S5P_WINCON_BYTESWP_DISABLE (0 << 17)
+#define S5P_WINCON_BYTESWP_ENABLE (1 << 17)
+#define S5P_WINCON_BYTESWP_SHIFT (17)
+#define S5P_WINCON_HAWSWP_DISABLE (0 << 16)
+#define S5P_WINCON_HAWSWP_ENABLE (1 << 16)
+#define S5P_WINCON_HAWSWP_SHIFT (16)
+#define S5P_WINCON_WSWP_DISABLE (0 << 15)
+#define S5P_WINCON_WSWP_ENABLE (1 << 15)
+#define S5P_WINCON_WSWP_SHIFT (15)
+#define S5P_WINCON_INRGB_RGB (0 << 13)
+#define S5P_WINCON_INRGB_YUV (1 << 13)
+#define S5P_WINCON_INRGB_MASK (1 << 13)
+#define S5P_WINCON_BURSTLEN_16WORD (0 << 9)
+#define S5P_WINCON_BURSTLEN_8WORD (1 << 9)
+#define S5P_WINCON_BURSTLEN_4WORD (2 << 9)
+#define S5P_WINCON_BURSTLEN_MASK (3 << 9)
+#define S5P_WINCON_ALPHA_MULTI_DISABLE (0 << 7)
+#define S5P_WINCON_ALPHA_MULTI_ENABLE (1 << 7)
+#define S5P_WINCON_BLD_PLANE (0 << 6)
+#define S5P_WINCON_BLD_PIXEL (1 << 6)
+#define S5P_WINCON_BLD_MASK (1 << 6)
+#define S5P_WINCON_BPPMODE_1BPP (0 << 2)
+#define S5P_WINCON_BPPMODE_2BPP (1 << 2)
+#define S5P_WINCON_BPPMODE_4BPP (2 << 2)
+#define S5P_WINCON_BPPMODE_8BPP_PAL (3 << 2)
+#define S5P_WINCON_BPPMODE_8BPP (4 << 2)
+#define S5P_WINCON_BPPMODE_16BPP_565 (5 << 2)
+#define S5P_WINCON_BPPMODE_16BPP_A555 (6 << 2)
+#define S5P_WINCON_BPPMODE_18BPP_666 (8 << 2)
+#define S5P_WINCON_BPPMODE_18BPP_A665 (9 << 2)
+#define S5P_WINCON_BPPMODE_24BPP_888 (0xb << 2)
+#define S5P_WINCON_BPPMODE_24BPP_A887 (0xc << 2)
+#define S5P_WINCON_BPPMODE_32BPP (0xd << 2)
+#define S5P_WINCON_BPPMODE_16BPP_A444 (0xe << 2)
+#define S5P_WINCON_BPPMODE_15BPP_555 (0xf << 2)
+#define S5P_WINCON_BPPMODE_MASK (0xf << 2)
+#define S5P_WINCON_BPPMODE_SHIFT (2)
+#define S5P_WINCON_ALPHA0_SEL (0 << 1)
+#define S5P_WINCON_ALPHA1_SEL (1 << 1)
+#define S5P_WINCON_ALPHA_SEL_MASK (1 << 1)
+#define S5P_WINCON_ENWIN_DISABLE (0 << 0)
+#define S5P_WINCON_ENWIN_ENABLE (1 << 0)
+
+/* WINCON1 special */
+#define S5P_WINCON1_VP_DISABLE (0 << 24)
+#define S5P_WINCON1_VP_ENABLE (1 << 24)
+#define S5P_WINCON1_LOCALSEL_FIMC1 (0 << 23)
+#define S5P_WINCON1_LOCALSEL_VP (1 << 23)
+#define S5P_WINCON1_LOCALSEL_MASK (1 << 23)
+
+/* WINSHMAP */
+#define S5P_SHADOWCON_PROTECT(x) (1 << (10 + x))
+#define S5P_SHADOWCON_CH_ENABLE(x) (1 << (x))
+#define S5P_SHADOWCON_CH_DISABLE(x) (1 << (x))
+
+
+/* VIDOSDxA, VIDOSDxB */
+#define S5P_VIDOSD_LEFT_X(x) (((x) & 0x7ff) << 11)
+#define S5P_VIDOSD_TOP_Y(x) (((x) & 0x7ff) << 0)
+#define S5P_VIDOSD_RIGHT_X(x) (((x) & 0x7ff) << 11)
+#define S5P_VIDOSD_BOTTOM_Y(x) (((x) & 0x7ff) << 0)
+
+/* VIDOSD0C, VIDOSDxD */
+#define S5P_VIDOSD_SIZE(x) (((x) & 0xffffff) << 0)
+
+/* VIDOSDxC (1~4) */
+#define S5P_VIDOSD_ALPHA0_R(x) (((x) & 0xf) << 20)
+#define S5P_VIDOSD_ALPHA0_G(x) (((x) & 0xf) << 16)
+#define S5P_VIDOSD_ALPHA0_B(x) (((x) & 0xf) << 12)
+#define S5P_VIDOSD_ALPHA1_R(x) (((x) & 0xf) << 8)
+#define S5P_VIDOSD_ALPHA1_G(x) (((x) & 0xf) << 4)
+#define S5P_VIDOSD_ALPHA1_B(x) (((x) & 0xf) << 0)
+#define S5P_VIDOSD_ALPHA0_SHIFT (12)
+#define S5P_VIDOSD_ALPHA1_SHIFT (0)
+
+/* Start Address */
+#define S5P_VIDADDR_START_VBANK(x) (((x) & 0xff) << 24)
+#define S5P_VIDADDR_START_VBASEU(x) (((x) & 0xffffff) << 0)
+
+/* End Address */
+#define S5P_VIDADDR_END_VBASEL(x) (((x) & 0xffffff) << 0)
+
+/* Buffer Size */
+#define S5P_VIDADDR_OFFSIZE(x) (((x) & 0x1fff) << 13)
+#define S5P_VIDADDR_PAGEWIDTH(x) (((x) & 0x1fff) << 0)
+
+/* WIN Color Map */
+#define S5P_WINMAP_COLOR(x) ((x) & 0xffffff)
+
+/* VIDINTCON0 */
+#define S5P_VIDINTCON0_SYSMAINCON_DISABLE (0 << 19)
+#define S5P_VIDINTCON0_SYSMAINCON_ENABLE (1 << 19)
+#define S5P_VIDINTCON0_SYSSUBCON_DISABLE (0 << 18)
+#define S5P_VIDINTCON0_SYSSUBCON_ENABLE (1 << 18)
+#define S5P_VIDINTCON0_SYSIFDONE_DISABLE (0 << 17)
+#define S5P_VIDINTCON0_SYSIFDONE_ENABLE (1 << 17)
+#define S5P_VIDINTCON0_FRAMESEL0_BACK (0 << 15)
+#define S5P_VIDINTCON0_FRAMESEL0_VSYNC (1 << 15)
+#define S5P_VIDINTCON0_FRAMESEL0_ACTIVE (2 << 15)
+#define S5P_VIDINTCON0_FRAMESEL0_FRONT (3 << 15)
+#define S5P_VIDINTCON0_FRAMESEL0_MASK (3 << 15)
+#define S5P_VIDINTCON0_FRAMESEL1_NONE (0 << 13)
+#define S5P_VIDINTCON0_FRAMESEL1_BACK (1 << 13)
+#define S5P_VIDINTCON0_FRAMESEL1_VSYNC (2 << 13)
+#define S5P_VIDINTCON0_FRAMESEL1_FRONT (3 << 13)
+#define S5P_VIDINTCON0_INTFRMEN_DISABLE (0 << 12)
+#define S5P_VIDINTCON0_INTFRMEN_ENABLE (1 << 12)
+#define S5P_VIDINTCON0_FIFOSEL_WIN4 (1 << 11)
+#define S5P_VIDINTCON0_FIFOSEL_WIN3 (1 << 10)
+#define S5P_VIDINTCON0_FIFOSEL_WIN2 (1 << 9)
+#define S5P_VIDINTCON0_FIFOSEL_WIN1 (1 << 6)
+#define S5P_VIDINTCON0_FIFOSEL_WIN0 (1 << 5)
+#define S5P_VIDINTCON0_FIFOSEL_ALL (0x73 << 5)
+#define S5P_VIDINTCON0_FIFOSEL_MASK (0x73 << 5)
+#define S5P_VIDINTCON0_FIFOLEVEL_25 (0 << 2)
+#define S5P_VIDINTCON0_FIFOLEVEL_50 (1 << 2)
+#define S5P_VIDINTCON0_FIFOLEVEL_75 (2 << 2)
+#define S5P_VIDINTCON0_FIFOLEVEL_EMPTY (3 << 2)
+#define S5P_VIDINTCON0_FIFOLEVEL_FULL (4 << 2)
+#define S5P_VIDINTCON0_FIFOLEVEL_MASK (7 << 2)
+#define S5P_VIDINTCON0_INTFIFO_DISABLE (0 << 1)
+#define S5P_VIDINTCON0_INTFIFO_ENABLE (1 << 1)
+#define S5P_VIDINTCON0_INT_DISABLE (0 << 0)
+#define S5P_VIDINTCON0_INT_ENABLE (1 << 0)
+#define S5P_VIDINTCON0_INT_MASK (1 << 0)
+
+/* VIDINTCON1 */
+#define S5P_VIDINTCON1_INTVPPEND (1 << 5)
+#define S5P_VIDINTCON1_INTI80PEND (1 << 2)
+#define S5P_VIDINTCON1_INTFRMPEND (1 << 1)
+#define S5P_VIDINTCON1_INTFIFOPEND (1 << 0)
+
+/* WINMAP */
+#define S5P_WINMAP_ENABLE (1 << 24)
+
+/* WxKEYCON0 (1~4) */
+#define S5P_KEYCON0_KEYBLEN_DISABLE (0 << 26)
+#define S5P_KEYCON0_KEYBLEN_ENABLE (1 << 26)
+#define S5P_KEYCON0_KEY_DISABLE (0 << 25)
+#define S5P_KEYCON0_KEY_ENABLE (1 << 25)
+#define S5P_KEYCON0_DIRCON_MATCH_FG (0 << 24)
+#define S5P_KEYCON0_DIRCON_MATCH_BG (1 << 24)
+#define S5P_KEYCON0_COMPKEY(x) (((x) & 0xffffff) << 0)
+
+/* WxKEYCON1 (1~4) */
+#define S5P_KEYCON1_COLVAL(x) (((x) & 0xffffff) << 0)
+
+
+#endif // _Display_Dxe_H__
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.inf
new file mode 100644
index 000000000..3667e00a2
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.inf
@@ -0,0 +1,65 @@
+## @file
+#
+# Component description file for GraphicsConsole module
+#
+# This is the main routine for initializing the Graphics Console support routines.
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = DisplayDxe
+ FILE_GUID = c5deae31-fad2-4030-841b-cfc9644d2c5b
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = DisplayDxeInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gGraphicsConsoleDriverBinding
+# COMPONENT_NAME = gGraphicsConsoleComponentName
+# COMPONENT_NAME2 = gGraphicsConsoleComponentName2
+#
+
+[Sources]
+ DisplayDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+ SamsungPlatformPkg/SamsungPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ IoLib
+ TimerLib
+
+[Protocols]
+ gEfiGraphicsOutputProtocolGuid ## TO_START
+ gSamsungPlatformGpioProtocolGuid ## GPIO Protocol
+
+[Guids]
+
+[Pcd]
+ gExynosPkgTokenSpaceGuid.PcdCmuBase
+ gExynosPkgTokenSpaceGuid.PcdPmuBase
+ gExynosPkgTokenSpaceGuid.PcdSysBase
+ gExynosPkgTokenSpaceGuid.PcdFIMD1Base
+ gExynosPkgTokenSpaceGuid.PcdFrameBufferBase
+ gExynosPkgTokenSpaceGuid.PcdDSIM1Base
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.c
new file mode 100644
index 000000000..51a8c1617
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.c
@@ -0,0 +1,788 @@
+/** @file
+ Template for Timer Architecture Protocol driver of the ARM flavor
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/NetLib.h>
+#include <Library/TimerLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/ExynosGpio.h>
+#include <Platform/ArmPlatform.h>
+#include "EthDxe.h"
+
+
+ETH_DXE_PRIVATE_DATA gEthDxePrivateTemplate = {
+ ETH_DXE_PRIVATE_DATA_SIGNATURE,
+ {
+ EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
+ EthStart,
+ EthStop,
+ EthInitialize,
+ EthReset,
+ EthShutdown,
+ EthReceiveFilters,
+ EthStationAddress,
+ EthStatistics,
+ EthMCastIpToMac,
+ EthNvData,
+ EthGetStatus,
+ EthTransmit,
+ EthReceive,
+ NULL,
+ NULL
+ },
+ {
+ EfiSimpleNetworkStopped, // State
+ NET_ETHER_ADDR_LEN, // HwAddressSize
+ NET_ETHER_HEADER_SIZE, // MediaHeaderSize
+ 1500, // MaxPacketSize
+ 0, // NvRamSize
+ 0, // NvRamAccessSize
+ 0, // ReceiveFilterMask
+ 0, // ReceiveFilterSetting
+ MAX_MCAST_FILTER_CNT, // MaxMCastFilterCount
+ 0, // MCastFilterCount
+ {
+ 0
+ }, // MCastFilter
+ {
+ 0
+ }, // CurrentAddress
+ {
+ 0
+ }, // BroadcastAddress
+ {
+ 0
+ }, // PermanentAddress
+ NET_IFTYPE_ETHERNET, // IfType
+ FALSE, // MacAddressChangeable
+ FALSE, // MultipleTxSupported
+ FALSE, // MediaPresentSupported
+ TRUE // MediaPresent
+ },
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
+ EFI_SIMPLE_NETWORK_PROTOCOL_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0
+ }
+ }
+};
+
+
+UINT32 smc911x_reg_read(UINT32 offset)
+{
+ UINT32 regBase = PcdGet32(PcdSMC911XBase);
+ UINT32 val;
+
+ val = (MmioRead16(regBase + offset) & 0xFFFF) | ((MmioRead16(regBase + offset + 2) & 0xFFFF) << 16);
+
+ return val;
+}
+
+VOID smc911x_reg_write(UINT32 offset, UINT32 val)
+{
+ UINT32 regBase = PcdGet32(PcdSMC911XBase);
+
+ MmioWrite16(regBase + offset, ((UINT16)(val & 0xFFFF)));
+ MmioWrite16(regBase + offset + 2, ((UINT16)((val & 0xFFFF0000)>>16)));
+}
+
+UINT32 smc911x_get_mac_csr(UINT8 reg)
+{
+ while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ ;
+ smc911x_reg_write(MAC_CSR_CMD, (MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg));
+ while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ ;
+ return smc911x_reg_read(MAC_CSR_DATA);
+}
+
+VOID smc911x_set_mac_csr(UINT8 reg, UINT32 data)
+{
+ while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ ;
+ smc911x_reg_write(MAC_CSR_DATA, data);
+ smc911x_reg_write(MAC_CSR_CMD, (MAC_CSR_CMD_CSR_BUSY | reg));
+ while (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
+ ;
+}
+
+VOID smc911x_reset(VOID)
+{
+ INT32 timeout;
+
+ /* Take out of PM setting first */
+ if (smc911x_reg_read(PMT_CTRL) & PMT_CTRL_READY) {
+ /* Write to the bytetest will take out of powerdown */
+ smc911x_reg_write(BYTE_TEST, 0x0);
+
+ timeout = 10;
+
+ while (timeout-- && !(smc911x_reg_read(PMT_CTRL) & PMT_CTRL_READY))
+ MicroSecondDelay(10);
+ if (!timeout) {
+ DEBUG((EFI_D_ERROR, "smc911x_reset: timeout waiting for PM restore\n"));
+ return;
+ }
+ }
+
+ /* Disable interrupts */
+ smc911x_reg_write(INT_EN, 0);
+
+ smc911x_reg_write(HW_CFG, HW_CFG_SRST);
+
+ timeout = 1000;
+ while (timeout-- && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY))
+ MicroSecondDelay(10);
+
+ if (!timeout) {
+ DEBUG((EFI_D_ERROR, "smc911x_reset: reset timeout\n"));
+ return;
+ }
+
+ /* Reset the FIFO level and flow control settings */
+ smc911x_set_mac_csr(FLOW, FLOW_FCPT | FLOW_FCEN);
+ smc911x_reg_write(AFC_CFG, 0x0050287F);
+
+ /* Set to LED outputs */
+ smc911x_reg_write(GPIO_CFG, 0x70070000);
+}
+
+VOID smc911x_phy_reset(VOID)
+{
+ UINT32 reg;
+
+ reg = smc911x_reg_read(PMT_CTRL);
+ reg &= ~0xfffff030;
+ reg |= PMT_CTRL_PHY_RST;
+ smc911x_reg_write(PMT_CTRL, reg);
+
+ MicroSecondDelay(100000);
+}
+
+VOID smc911x_miiphy_read(UINT8 phy, UINT8 reg, UINT16 *val)
+{
+ while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)
+ ;
+
+ smc911x_set_mac_csr(MII_ACC, (phy << 11 | reg << 6 | MII_ACC_MII_BUSY));
+
+ while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)
+ ;
+
+ *val = smc911x_get_mac_csr(MII_DATA);
+}
+
+VOID smc911x_miiphy_write(UINT8 phy, UINT8 reg, UINT16 val)
+{
+ while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)
+ ;
+
+ smc911x_set_mac_csr(MII_DATA, val);
+ smc911x_set_mac_csr(MII_ACC, (phy << 11 | reg << 6 | MII_ACC_MII_BUSY | MII_ACC_MII_WRITE));
+
+ while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY)
+ ;
+}
+
+VOID smc911x_phy_configure(VOID)
+{
+ INT32 timeout;
+ UINT16 status;
+
+ smc911x_phy_reset();
+
+ smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_RESET);
+ MicroSecondDelay(1000);
+ smc911x_miiphy_write(1, PHY_ANAR, 0x01e1);
+ smc911x_miiphy_write(1, PHY_BMCR, (PHY_BMCR_AUTON | PHY_BMCR_RST_NEG));
+
+ timeout = 5000;
+ do {
+ MicroSecondDelay(1000);
+ if ((timeout--) == 0)
+ goto err_out;
+
+ smc911x_miiphy_read(1, PHY_BMSR, &status);
+ } while (!(status & PHY_BMSR_LS));
+
+ DEBUG((EFI_D_ERROR, "smc911x_phy_configure: PHY initialized\n"));
+
+ return;
+
+err_out:
+ DEBUG((EFI_D_ERROR, "smc911x_phy_configure: autonegotiation timed out\n"));
+}
+
+VOID smc911x_handle_mac_address(ETH_DXE_PRIVATE_DATA *Private)
+{
+ UINT32 addrh, addrl;
+
+ addrl = Private->Mode.CurrentAddress.Addr[0] | \
+ (Private->Mode.CurrentAddress.Addr[1] << 8) | \
+ (Private->Mode.CurrentAddress.Addr[2] << 16) | \
+ (Private->Mode.CurrentAddress.Addr[3] << 24);
+ addrh = Private->Mode.CurrentAddress.Addr[4] | \
+ (Private->Mode.CurrentAddress.Addr[5] << 8);
+
+ smc911x_set_mac_csr(ADDRL, addrl);
+ smc911x_set_mac_csr(ADDRH, addrh);
+}
+
+VOID smc911x_enable(VOID)
+{
+ /* Enable TX */
+ smc911x_reg_write(HW_CFG, (8 << 16 | HW_CFG_SF));
+
+ smc911x_reg_write(GPT_CFG, (GPT_CFG_TIMER_EN | 10000));
+
+ smc911x_reg_write(TX_CFG, TX_CFG_TX_ON);
+
+ /* no padding to start of packets */
+ smc911x_reg_write(RX_CFG, 0);
+
+ smc911x_set_mac_csr(MAC_CR, (MAC_CR_TXEN | MAC_CR_RXEN | MAC_CR_HBDIS /*| MAC_CR_PADSTR*/));
+}
+
+EFI_STATUS
+EFIAPI
+EthStart(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This
+)
+{
+ ETH_DXE_PRIVATE_DATA *Private;
+
+ Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This);
+
+ switch ( Private->Snp.Mode->State )
+ {
+ case EfiSimpleNetworkStopped:
+ break;
+
+ case EfiSimpleNetworkStarted:
+ case EfiSimpleNetworkInitialized:
+ return( EFI_ALREADY_STARTED );
+ break;
+
+ default:
+ return( EFI_DEVICE_ERROR );
+ break;
+ }
+
+ /* gpio configuration */
+ MmioAndThenOr32(0x11000000 + 0x120, ~((0xFF<<16)|(0xFF<<4)), ((0x22<<16)|(0x52<<4)));
+
+ /* 16 Bit bus width */
+ MmioWrite32(0x11000000 + 0x1C0, 0x22222222);
+ MmioWrite32(0x11000000 + 0x1E0, 0x22222222);
+
+ /* SROM BANK1 */
+ MmioAndThenOr32(0x12570000, ~(0xF<<4), (((1<<0)|(0<<2)|(1<<3))<<4));
+
+ /* set timing for nCS1 suitable for ethernet chip */
+ MmioWrite32(0x12570008, ((0x1 << 0) | (0x9 << 4) | (0xC << 8) | (0x1 << 12) | \
+ (0x6 << 16) | (0x1 << 24) | (0x1 << 28)));
+
+ Private->Snp.Mode->State = EfiSimpleNetworkStarted;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+EthStop(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This
+)
+{
+ ETH_DXE_PRIVATE_DATA *Private;
+
+ Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This);
+
+ switch ( Private->Snp.Mode->State )
+ {
+ case EfiSimpleNetworkStarted:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return( EFI_NOT_STARTED );
+ break;
+
+ default:
+ return( EFI_DEVICE_ERROR );
+ break;
+ }
+
+ Private->Snp.Mode->State = EfiSimpleNetworkStopped;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+EthInitialize(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINTN ExtraRxBufferSize,
+ UINTN ExtraTxBufferSize
+)
+{
+ UINT32 val, i, addrh, addrl;
+ ETH_DXE_PRIVATE_DATA *Private;
+
+ Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This);
+
+ switch ( Private->Snp.Mode->State )
+ {
+ case EfiSimpleNetworkStarted:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return( EFI_NOT_STARTED );
+ break;
+
+ default:
+ return( EFI_DEVICE_ERROR );
+ break;
+ }
+
+ val = smc911x_reg_read(BYTE_TEST);
+
+ if(val == 0xFFFFFFFF) {
+ return EFI_NO_MEDIA;
+ }
+ else if(val != 0x87654321) {
+ DEBUG((EFI_D_ERROR,"EthInitialize: Invalid chip endian 0x%x\n", val));
+ return EFI_NO_MEDIA;
+ }
+
+ val = smc911x_reg_read(ID_REV) >> 16;
+ for(i=0;chip_ids[i].id != 0;i++) {
+ if(chip_ids[i].id == val)
+ break;
+ }
+
+ if(!chip_ids[i].id) {
+ DEBUG((EFI_D_ERROR,"EthInitialize: Unknown chip id 0x%x\n", val));
+ return EFI_NO_MEDIA;
+ }
+ else {
+ DEBUG((EFI_D_ERROR,"EthInitialize: Chip id 0x%x\n", val));
+ }
+
+ addrh = smc911x_get_mac_csr(ADDRH);
+ addrl = smc911x_get_mac_csr(ADDRL);
+
+ if (addrl == 0xffffffff && addrh == 0x0000ffff) {
+ addrh = 0x00000040;
+ addrl = 0x5c260a5b;
+ }
+
+ Private->Mode.CurrentAddress.Addr[0] = (addrl & 0xFF);
+ Private->Mode.CurrentAddress.Addr[1] = (addrl & 0xFF00)>>8;
+ Private->Mode.CurrentAddress.Addr[2] = (addrl & 0xFF0000)>>16;
+ Private->Mode.CurrentAddress.Addr[3] = (addrl & 0xFF000000)>>24;
+ Private->Mode.CurrentAddress.Addr[4] = (addrh & 0xFF);
+ Private->Mode.CurrentAddress.Addr[5] = (addrh & 0xFF00)>>8;
+ gBS->CopyMem((VOID *)&Private->Mode.PermanentAddress, \
+ (VOID *)&Private->Mode.CurrentAddress, \
+ sizeof(EFI_MAC_ADDRESS));
+
+ DEBUG((EFI_D_ERROR,"EthInitialize: MAC address is "));
+
+ for(i=6;i>0;i--) {
+ DEBUG((EFI_D_ERROR,"%02x", Private->Mode.CurrentAddress.Addr[i - 1]));
+ if(i > 1)
+ DEBUG((EFI_D_ERROR,":"));
+ else
+ DEBUG((EFI_D_ERROR,"\n"));
+ }
+
+ smc911x_reset();
+
+ /* Configure the PHY, initialize the link state */
+ smc911x_phy_configure();
+
+ smc911x_handle_mac_address(Private);
+
+ /* Turn on Tx + Rx */
+ smc911x_enable();
+
+ Private->Snp.Mode->State = EfiSimpleNetworkInitialized;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+EthReset(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN ExtendedVerification
+)
+{
+ ETH_DXE_PRIVATE_DATA *Private;
+
+ Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This);
+
+ switch ( Private->Snp.Mode->State )
+ {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return( EFI_NOT_STARTED );
+ break;
+
+ default:
+ return( EFI_DEVICE_ERROR );
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+EthShutdown(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This
+)
+{
+ ETH_DXE_PRIVATE_DATA *Private;
+
+ Private = ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(This);
+
+ switch ( Private->Snp.Mode->State )
+ {
+ case EfiSimpleNetworkInitialized:
+ break;
+
+ case EfiSimpleNetworkStopped:
+ return( EFI_NOT_STARTED );
+ break;
+
+ default:
+ return( EFI_DEVICE_ERROR );
+ break;
+ }
+
+ Private->Snp.Mode->State = EfiSimpleNetworkStarted;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+EthReceiveFilters(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINT32 Enable,
+ UINT32 Disable,
+ BOOLEAN ResetMCastFilter,
+ UINTN MCastFilterCnt,
+ EFI_MAC_ADDRESS *MCastFilter
+)
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+EthStationAddress(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN Reset,
+ EFI_MAC_ADDRESS *New
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+EthStatistics(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN Reset,
+ UINTN *StatisticsSize,
+ EFI_NETWORK_STATISTICS *StatisticsTable
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+EthMCastIpToMac(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN IPv6,
+ EFI_IP_ADDRESS *IP,
+ EFI_MAC_ADDRESS *MAC
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+EthNvData(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN ReadWrite,
+ UINTN Offset,
+ UINTN BufferSize,
+ VOID *Buffer
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+EthGetStatus(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINT32 *InterruptStatus,
+ VOID **TxBuf
+)
+{
+ if ( TxBuf != NULL ) {
+ *( ( UINT8 ** ) TxBuf ) = ( UINT8 * ) 1;
+ }
+
+ if ( InterruptStatus != NULL ) {
+ *InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+EthTransmit(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINTN HeaderSize,
+ UINTN BufferSize,
+ VOID *Buffer,
+ EFI_MAC_ADDRESS *SrcAddr,
+ EFI_MAC_ADDRESS *DestAddr,
+ UINT16 *Protocol
+)
+{
+ UINT32 *data = (UINT32 *)Buffer;
+ UINT32 tmpSize;
+ UINT32 status;
+ EthernetHeader *EnetHeader;
+
+ if ( This->Mode->State < EfiSimpleNetworkStarted ) {
+ return( EFI_NOT_STARTED );
+ }
+
+ if ( HeaderSize != 0 ) {
+ if ( ( DestAddr == NULL ) || ( Protocol == NULL ) || \
+ ( HeaderSize != This->Mode->MediaHeaderSize ) ) {
+ return( EFI_INVALID_PARAMETER );
+ }
+
+ if ( SrcAddr == NULL ) {
+ SrcAddr = &This->Mode->CurrentAddress;
+ }
+
+ EnetHeader = (EthernetHeader *)Buffer;
+
+ CopyMem( EnetHeader->DstAddr, DestAddr, NET_ETHER_ADDR_LEN );
+ CopyMem( EnetHeader->SrcAddr, SrcAddr, NET_ETHER_ADDR_LEN );
+
+ EnetHeader->Type = HTONS( *Protocol );
+ }
+
+ smc911x_reg_write(TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG | TX_CMD_A_INT_LAST_SEG | BufferSize);
+ smc911x_reg_write(TX_DATA_FIFO, BufferSize);
+
+ tmpSize = (BufferSize + 3) / 4;
+
+ while (tmpSize--)
+ smc911x_reg_write(TX_DATA_FIFO, *data++);
+
+ /* wait for transmission */
+ while (!((smc911x_reg_read(TX_FIFO_INF) & TX_FIFO_INF_TSUSED) >> 16))
+ ;
+
+ /* get status. Ignore 'no carrier' error, it has no meaning for
+ * full duplex operation
+ */
+ status = smc911x_reg_read(TX_STATUS_FIFO) & \
+ (TX_STS_LOC | TX_STS_LATE_COLL | \
+ TX_STS_MANY_COLL | TX_STS_MANY_DEFER | \
+ TX_STS_UNDERRUN);
+
+ if (!status)
+ return EFI_SUCCESS;
+
+ DEBUG((EFI_D_ERROR, "EthTransmit: Failed to send packet: %s%s%s%s%s\n",
+ status & TX_STS_LOC ? "TX_STS_LOC " : "",
+ status & TX_STS_LATE_COLL ? "TX_STS_LATE_COLL " : "",
+ status & TX_STS_MANY_COLL ? "TX_STS_MANY_COLL " : "",
+ status & TX_STS_MANY_DEFER ? "TX_STS_MANY_DEFER " : "",
+ status & TX_STS_UNDERRUN ? "TX_STS_UNDERRUN" : ""));
+
+ return EFI_DEVICE_ERROR;
+}
+
+EFI_STATUS
+EFIAPI
+EthReceive(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINTN *HeaderSize,
+ UINTN *BufferSize,
+ VOID *Buffer,
+ EFI_MAC_ADDRESS *SrcAddr,
+ EFI_MAC_ADDRESS *DestAddr,
+ UINT16 *Protocol
+)
+{
+ UINT32 *data = (UINT32 *)Buffer;
+ UINT32 pktSize, tmpSize;
+ UINT32 status, i;
+ EthernetHeader *EnetHeader;
+
+ /* workaround: delay for rx packet should be added here.
+ * because NetLoop does not guarantee the RX packet delay.
+ */
+ for (i=0; i<0x100000; i++) {
+ if ((smc911x_reg_read(RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16)
+ break;
+ }
+
+ if (i == 0x100000) {
+ DEBUG((EFI_D_ERROR, "EthReceive: timeout in RX\n"));
+ return EFI_TIMEOUT;
+ }
+
+ if ((smc911x_reg_read(RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) {
+ status = smc911x_reg_read(RX_STATUS_FIFO);
+ pktSize = (status & RX_STS_PKT_LEN) >> 16;
+
+ smc911x_reg_write(RX_CFG, 0);
+
+ tmpSize = (pktSize + 3) / 4;
+ i = 0;
+ while (tmpSize--)
+ *data++ = smc911x_reg_read(RX_DATA_FIFO);
+
+ if (status & RX_STS_ES) {
+ DEBUG((EFI_D_ERROR, "EthReceive: dropped bad packet. Status: 0x%x\n", status));
+ }
+
+ *BufferSize = pktSize -4; //discard 4 bytes of FCS
+
+ }
+
+#if 0
+ {
+ UINT8 *tmpBuffer = (UINT8 *)Buffer;
+
+ for(i=0;i<*BufferSize;i++) {
+ DEBUG((EFI_D_ERROR, "%02x", *tmpBuffer++));
+ if((i%16) < 15)
+ DEBUG((EFI_D_ERROR, " "));
+ else
+ DEBUG((EFI_D_ERROR, "\n"));
+ }
+
+ DEBUG((EFI_D_ERROR, "\n"));
+ }
+#endif
+
+ if(HeaderSize != NULL) {
+ *HeaderSize = sizeof(EthernetHeader);
+ }
+
+ EnetHeader = (EthernetHeader *)Buffer;
+
+ if(SrcAddr != NULL) {
+ ZeroMem(SrcAddr, sizeof(EFI_MAC_ADDRESS));
+ CopyMem(SrcAddr, EnetHeader->SrcAddr, NET_ETHER_ADDR_LEN);
+ }
+
+ if(DestAddr != NULL) {
+ ZeroMem(DestAddr, sizeof(EFI_MAC_ADDRESS));
+ CopyMem(DestAddr, EnetHeader->DstAddr, NET_ETHER_ADDR_LEN);
+ }
+
+ if (Protocol != NULL) {
+ *Protocol = NTOHS(EnetHeader->Type);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize the state information for the Display Dxe
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+EthDxeInitialize (
+ EFI_HANDLE ImageHandle,
+ EFI_SYSTEM_TABLE *SystemTable
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_GUID SimpleNetworkProtocolGuid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
+ EFI_GUID DevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+ ETH_DXE_PRIVATE_DATA *Private;
+
+ /* Allocate the private data */
+ Private = (ETH_DXE_PRIVATE_DATA *)AllocateCopyPool(sizeof(ETH_DXE_PRIVATE_DATA), &gEthDxePrivateTemplate );
+ if ( Private == NULL ) {
+ Status = EFI_OUT_OF_RESOURCES;
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ Private->Snp.Mode = &Private->Mode;
+
+ /* Set the broadcast address */
+ SetMem( &Private->Mode.BroadcastAddress, sizeof( EFI_MAC_ADDRESS ), 0xFF );
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &DevicePathProtocolGuid,
+ &Private->DevicePath,
+ &SimpleNetworkProtocolGuid,
+ &Private->Snp,
+ NULL);
+
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.h
new file mode 100644
index 000000000..3b9a790eb
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.h
@@ -0,0 +1,612 @@
+/** @file
+*
+* Copyright (c) 2012, Samsung Electronics Co. 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 _EthDxe_H__
+#define _EthDxe_H__
+
+#define NET_ETHER_HEADER_SIZE 14
+
+typedef struct
+{
+ UINT8 DstAddr[ NET_ETHER_ADDR_LEN ];
+ UINT8 SrcAddr[ NET_ETHER_ADDR_LEN ];
+ UINT16 Type;
+} EthernetHeader;
+
+/* Chip ID values */
+#define CHIP_9115 0x115
+#define CHIP_9116 0x116
+#define CHIP_9117 0x117
+#define CHIP_9118 0x118
+#define CHIP_9211 0x9211
+#define CHIP_9215 0x115a
+#define CHIP_9216 0x116a
+#define CHIP_9217 0x117a
+#define CHIP_9218 0x118a
+#define CHIP_9220 0x9220
+#define CHIP_9221 0x9221
+
+struct chip_id {
+ UINT16 id;
+ CHAR8 *name;
+};
+
+static const struct chip_id chip_ids[] = {
+ { CHIP_9115, "LAN9115" },
+ { CHIP_9116, "LAN9116" },
+ { CHIP_9117, "LAN9117" },
+ { CHIP_9118, "LAN9118" },
+ { CHIP_9211, "LAN9211" },
+ { CHIP_9215, "LAN9215" },
+ { CHIP_9216, "LAN9216" },
+ { CHIP_9217, "LAN9217" },
+ { CHIP_9218, "LAN9218" },
+ { CHIP_9220, "LAN9220" },
+ { CHIP_9221, "LAN9221" },
+ { 0, NULL },
+};
+
+
+/* Below are the register offsets and bit definitions
+ * of the Lan911x memory space
+ */
+#define RX_DATA_FIFO 0x00
+
+#define TX_DATA_FIFO 0x20
+#define TX_CMD_A_INT_ON_COMP 0x80000000
+#define TX_CMD_A_INT_BUF_END_ALGN 0x03000000
+#define TX_CMD_A_INT_4_BYTE_ALGN 0x00000000
+#define TX_CMD_A_INT_16_BYTE_ALGN 0x01000000
+#define TX_CMD_A_INT_32_BYTE_ALGN 0x02000000
+#define TX_CMD_A_INT_DATA_OFFSET 0x001F0000
+#define TX_CMD_A_INT_FIRST_SEG 0x00002000
+#define TX_CMD_A_INT_LAST_SEG 0x00001000
+#define TX_CMD_A_BUF_SIZE 0x000007FF
+#define TX_CMD_B_PKT_TAG 0xFFFF0000
+#define TX_CMD_B_ADD_CRC_DISABLE 0x00002000
+#define TX_CMD_B_DISABLE_PADDING 0x00001000
+#define TX_CMD_B_PKT_BYTE_LENGTH 0x000007FF
+
+#define RX_STATUS_FIFO 0x40
+#define RX_STS_PKT_LEN 0x3FFF0000
+#define RX_STS_ES 0x00008000
+#define RX_STS_BCST 0x00002000
+#define RX_STS_LEN_ERR 0x00001000
+#define RX_STS_RUNT_ERR 0x00000800
+#define RX_STS_MCAST 0x00000400
+#define RX_STS_TOO_LONG 0x00000080
+#define RX_STS_COLL 0x00000040
+#define RX_STS_ETH_TYPE 0x00000020
+#define RX_STS_WDOG_TMT 0x00000010
+#define RX_STS_MII_ERR 0x00000008
+#define RX_STS_DRIBBLING 0x00000004
+#define RX_STS_CRC_ERR 0x00000002
+#define RX_STATUS_FIFO_PEEK 0x44
+#define TX_STATUS_FIFO 0x48
+#define TX_STS_TAG 0xFFFF0000
+#define TX_STS_ES 0x00008000
+#define TX_STS_LOC 0x00000800
+#define TX_STS_NO_CARR 0x00000400
+#define TX_STS_LATE_COLL 0x00000200
+#define TX_STS_MANY_COLL 0x00000100
+#define TX_STS_COLL_CNT 0x00000078
+#define TX_STS_MANY_DEFER 0x00000004
+#define TX_STS_UNDERRUN 0x00000002
+#define TX_STS_DEFERRED 0x00000001
+#define TX_STATUS_FIFO_PEEK 0x4C
+#define ID_REV 0x50
+#define ID_REV_CHIP_ID 0xFFFF0000 /* RO */
+#define ID_REV_REV_ID 0x0000FFFF /* RO */
+
+#define INT_CFG 0x54
+#define INT_CFG_INT_DEAS 0xFF000000 /* R/W */
+#define INT_CFG_INT_DEAS_CLR 0x00004000
+#define INT_CFG_INT_DEAS_STS 0x00002000
+#define INT_CFG_IRQ_INT 0x00001000 /* RO */
+#define INT_CFG_IRQ_EN 0x00000100 /* R/W */
+ /* R/W Not Affected by SW Reset */
+#define INT_CFG_IRQ_POL 0x00000010
+ /* R/W Not Affected by SW Reset */
+#define INT_CFG_IRQ_TYPE 0x00000001
+
+#define INT_STS 0x58
+#define INT_STS_SW_INT 0x80000000 /* R/WC */
+#define INT_STS_TXSTOP_INT 0x02000000 /* R/WC */
+#define INT_STS_RXSTOP_INT 0x01000000 /* R/WC */
+#define INT_STS_RXDFH_INT 0x00800000 /* R/WC */
+#define INT_STS_RXDF_INT 0x00400000 /* R/WC */
+#define INT_STS_TX_IOC 0x00200000 /* R/WC */
+#define INT_STS_RXD_INT 0x00100000 /* R/WC */
+#define INT_STS_GPT_INT 0x00080000 /* R/WC */
+#define INT_STS_PHY_INT 0x00040000 /* RO */
+#define INT_STS_PME_INT 0x00020000 /* R/WC */
+#define INT_STS_TXSO 0x00010000 /* R/WC */
+#define INT_STS_RWT 0x00008000 /* R/WC */
+#define INT_STS_RXE 0x00004000 /* R/WC */
+#define INT_STS_TXE 0x00002000 /* R/WC */
+/*#define INT_STS_ERX 0x00001000*/ /* R/WC */
+#define INT_STS_TDFU 0x00000800 /* R/WC */
+#define INT_STS_TDFO 0x00000400 /* R/WC */
+#define INT_STS_TDFA 0x00000200 /* R/WC */
+#define INT_STS_TSFF 0x00000100 /* R/WC */
+#define INT_STS_TSFL 0x00000080 /* R/WC */
+/*#define INT_STS_RXDF 0x00000040*/ /* R/WC */
+#define INT_STS_RDFO 0x00000040 /* R/WC */
+#define INT_STS_RDFL 0x00000020 /* R/WC */
+#define INT_STS_RSFF 0x00000010 /* R/WC */
+#define INT_STS_RSFL 0x00000008 /* R/WC */
+#define INT_STS_GPIO2_INT 0x00000004 /* R/WC */
+#define INT_STS_GPIO1_INT 0x00000002 /* R/WC */
+#define INT_STS_GPIO0_INT 0x00000001 /* R/WC */
+#define INT_EN 0x5C
+#define INT_EN_SW_INT_EN 0x80000000 /* R/W */
+#define INT_EN_TXSTOP_INT_EN 0x02000000 /* R/W */
+#define INT_EN_RXSTOP_INT_EN 0x01000000 /* R/W */
+#define INT_EN_RXDFH_INT_EN 0x00800000 /* R/W */
+/*#define INT_EN_RXDF_INT_EN 0x00400000*/ /* R/W */
+#define INT_EN_TIOC_INT_EN 0x00200000 /* R/W */
+#define INT_EN_RXD_INT_EN 0x00100000 /* R/W */
+#define INT_EN_GPT_INT_EN 0x00080000 /* R/W */
+#define INT_EN_PHY_INT_EN 0x00040000 /* R/W */
+#define INT_EN_PME_INT_EN 0x00020000 /* R/W */
+#define INT_EN_TXSO_EN 0x00010000 /* R/W */
+#define INT_EN_RWT_EN 0x00008000 /* R/W */
+#define INT_EN_RXE_EN 0x00004000 /* R/W */
+#define INT_EN_TXE_EN 0x00002000 /* R/W */
+/*#define INT_EN_ERX_EN 0x00001000*/ /* R/W */
+#define INT_EN_TDFU_EN 0x00000800 /* R/W */
+#define INT_EN_TDFO_EN 0x00000400 /* R/W */
+#define INT_EN_TDFA_EN 0x00000200 /* R/W */
+#define INT_EN_TSFF_EN 0x00000100 /* R/W */
+#define INT_EN_TSFL_EN 0x00000080 /* R/W */
+/*#define INT_EN_RXDF_EN 0x00000040*/ /* R/W */
+#define INT_EN_RDFO_EN 0x00000040 /* R/W */
+#define INT_EN_RDFL_EN 0x00000020 /* R/W */
+#define INT_EN_RSFF_EN 0x00000010 /* R/W */
+#define INT_EN_RSFL_EN 0x00000008 /* R/W */
+#define INT_EN_GPIO2_INT 0x00000004 /* R/W */
+#define INT_EN_GPIO1_INT 0x00000002 /* R/W */
+#define INT_EN_GPIO0_INT 0x00000001 /* R/W */
+
+#define BYTE_TEST 0x64
+#define FIFO_INT 0x68
+#define FIFO_INT_TX_AVAIL_LEVEL 0xFF000000 /* R/W */
+#define FIFO_INT_TX_STS_LEVEL 0x00FF0000 /* R/W */
+#define FIFO_INT_RX_AVAIL_LEVEL 0x0000FF00 /* R/W */
+#define FIFO_INT_RX_STS_LEVEL 0x000000FF /* R/W */
+
+#define RX_CFG 0x6C
+#define RX_CFG_RX_END_ALGN 0xC0000000 /* R/W */
+#define RX_CFG_RX_END_ALGN4 0x00000000 /* R/W */
+#define RX_CFG_RX_END_ALGN16 0x40000000 /* R/W */
+#define RX_CFG_RX_END_ALGN32 0x80000000 /* R/W */
+#define RX_CFG_RX_DMA_CNT 0x0FFF0000 /* R/W */
+#define RX_CFG_RX_DUMP 0x00008000 /* R/W */
+#define RX_CFG_RXDOFF 0x00001F00 /* R/W */
+/*#define RX_CFG_RXBAD 0x00000001*/ /* R/W */
+
+#define TX_CFG 0x70
+/*#define TX_CFG_TX_DMA_LVL 0xE0000000*/ /* R/W */
+ /* R/W Self Clearing */
+/*#define TX_CFG_TX_DMA_CNT 0x0FFF0000*/
+#define TX_CFG_TXS_DUMP 0x00008000 /* Self Clearing */
+#define TX_CFG_TXD_DUMP 0x00004000 /* Self Clearing */
+#define TX_CFG_TXSAO 0x00000004 /* R/W */
+#define TX_CFG_TX_ON 0x00000002 /* R/W */
+#define TX_CFG_STOP_TX 0x00000001 /* Self Clearing */
+
+#define HW_CFG 0x74
+#define HW_CFG_TTM 0x00200000 /* R/W */
+#define HW_CFG_SF 0x00100000 /* R/W */
+#define HW_CFG_TX_FIF_SZ 0x000F0000 /* R/W */
+#define HW_CFG_TR 0x00003000 /* R/W */
+#define HW_CFG_PHY_CLK_SEL 0x00000060 /* R/W */
+#define HW_CFG_PHY_CLK_SEL_INT_PHY 0x00000000 /* R/W */
+#define HW_CFG_PHY_CLK_SEL_EXT_PHY 0x00000020 /* R/W */
+#define HW_CFG_PHY_CLK_SEL_CLK_DIS 0x00000040 /* R/W */
+#define HW_CFG_SMI_SEL 0x00000010 /* R/W */
+#define HW_CFG_EXT_PHY_DET 0x00000008 /* RO */
+#define HW_CFG_EXT_PHY_EN 0x00000004 /* R/W */
+#define HW_CFG_32_16_BIT_MODE 0x00000004 /* RO */
+#define HW_CFG_SRST_TO 0x00000002 /* RO */
+#define HW_CFG_SRST 0x00000001 /* Self Clearing */
+
+#define RX_DP_CTRL 0x78
+#define RX_DP_CTRL_RX_FFWD 0x80000000 /* R/W */
+#define RX_DP_CTRL_FFWD_BUSY 0x80000000 /* RO */
+
+#define RX_FIFO_INF 0x7C
+#define RX_FIFO_INF_RXSUSED 0x00FF0000 /* RO */
+#define RX_FIFO_INF_RXDUSED 0x0000FFFF /* RO */
+
+#define TX_FIFO_INF 0x80
+#define TX_FIFO_INF_TSUSED 0x00FF0000 /* RO */
+#define TX_FIFO_INF_TDFREE 0x0000FFFF /* RO */
+
+#define PMT_CTRL 0x84
+#define PMT_CTRL_PM_MODE 0x00003000 /* Self Clearing */
+#define PMT_CTRL_PHY_RST 0x00000400 /* Self Clearing */
+#define PMT_CTRL_WOL_EN 0x00000200 /* R/W */
+#define PMT_CTRL_ED_EN 0x00000100 /* R/W */
+ /* R/W Not Affected by SW Reset */
+#define PMT_CTRL_PME_TYPE 0x00000040
+#define PMT_CTRL_WUPS 0x00000030 /* R/WC */
+#define PMT_CTRL_WUPS_NOWAKE 0x00000000 /* R/WC */
+#define PMT_CTRL_WUPS_ED 0x00000010 /* R/WC */
+#define PMT_CTRL_WUPS_WOL 0x00000020 /* R/WC */
+#define PMT_CTRL_WUPS_MULTI 0x00000030 /* R/WC */
+#define PMT_CTRL_PME_IND 0x00000008 /* R/W */
+#define PMT_CTRL_PME_POL 0x00000004 /* R/W */
+ /* R/W Not Affected by SW Reset */
+#define PMT_CTRL_PME_EN 0x00000002
+#define PMT_CTRL_READY 0x00000001 /* RO */
+
+#define GPIO_CFG 0x88
+#define GPIO_CFG_LED3_EN 0x40000000 /* R/W */
+#define GPIO_CFG_LED2_EN 0x20000000 /* R/W */
+#define GPIO_CFG_LED1_EN 0x10000000 /* R/W */
+#define GPIO_CFG_GPIO2_INT_POL 0x04000000 /* R/W */
+#define GPIO_CFG_GPIO1_INT_POL 0x02000000 /* R/W */
+#define GPIO_CFG_GPIO0_INT_POL 0x01000000 /* R/W */
+#define GPIO_CFG_EEPR_EN 0x00700000 /* R/W */
+#define GPIO_CFG_GPIOBUF2 0x00040000 /* R/W */
+#define GPIO_CFG_GPIOBUF1 0x00020000 /* R/W */
+#define GPIO_CFG_GPIOBUF0 0x00010000 /* R/W */
+#define GPIO_CFG_GPIODIR2 0x00000400 /* R/W */
+#define GPIO_CFG_GPIODIR1 0x00000200 /* R/W */
+#define GPIO_CFG_GPIODIR0 0x00000100 /* R/W */
+#define GPIO_CFG_GPIOD4 0x00000010 /* R/W */
+#define GPIO_CFG_GPIOD3 0x00000008 /* R/W */
+#define GPIO_CFG_GPIOD2 0x00000004 /* R/W */
+#define GPIO_CFG_GPIOD1 0x00000002 /* R/W */
+#define GPIO_CFG_GPIOD0 0x00000001 /* R/W */
+
+#define GPT_CFG 0x8C
+#define GPT_CFG_TIMER_EN 0x20000000 /* R/W */
+#define GPT_CFG_GPT_LOAD 0x0000FFFF /* R/W */
+
+#define GPT_CNT 0x90
+#define GPT_CNT_GPT_CNT 0x0000FFFF /* RO */
+
+#define ENDIAN 0x98
+#define FREE_RUN 0x9C
+#define RX_DROP 0xA0
+#define MAC_CSR_CMD 0xA4
+#define MAC_CSR_CMD_CSR_BUSY 0x80000000 /* Self Clearing */
+#define MAC_CSR_CMD_R_NOT_W 0x40000000 /* R/W */
+#define MAC_CSR_CMD_CSR_ADDR 0x000000FF /* R/W */
+
+#define MAC_CSR_DATA 0xA8
+#define AFC_CFG 0xAC
+#define AFC_CFG_AFC_HI 0x00FF0000 /* R/W */
+#define AFC_CFG_AFC_LO 0x0000FF00 /* R/W */
+#define AFC_CFG_BACK_DUR 0x000000F0 /* R/W */
+#define AFC_CFG_FCMULT 0x00000008 /* R/W */
+#define AFC_CFG_FCBRD 0x00000004 /* R/W */
+#define AFC_CFG_FCADD 0x00000002 /* R/W */
+#define AFC_CFG_FCANY 0x00000001 /* R/W */
+
+#define E2P_CMD 0xB0
+#define E2P_CMD_EPC_BUSY 0x80000000 /* Self Clearing */
+#define E2P_CMD_EPC_CMD 0x70000000 /* R/W */
+#define E2P_CMD_EPC_CMD_READ 0x00000000 /* R/W */
+#define E2P_CMD_EPC_CMD_EWDS 0x10000000 /* R/W */
+#define E2P_CMD_EPC_CMD_EWEN 0x20000000 /* R/W */
+#define E2P_CMD_EPC_CMD_WRITE 0x30000000 /* R/W */
+#define E2P_CMD_EPC_CMD_WRAL 0x40000000 /* R/W */
+#define E2P_CMD_EPC_CMD_ERASE 0x50000000 /* R/W */
+#define E2P_CMD_EPC_CMD_ERAL 0x60000000 /* R/W */
+#define E2P_CMD_EPC_CMD_RELOAD 0x70000000 /* R/W */
+#define E2P_CMD_EPC_TIMEOUT 0x00000200 /* RO */
+#define E2P_CMD_MAC_ADDR_LOADED 0x00000100 /* RO */
+#define E2P_CMD_EPC_ADDR 0x000000FF /* R/W */
+
+#define E2P_DATA 0xB4
+#define E2P_DATA_EEPROM_DATA 0x000000FF /* R/W */
+/* end of LAN register offsets and bit definitions */
+
+/* MAC Control and Status registers */
+#define MAC_CR 0x01 /* R/W */
+
+/* MAC_CR - MAC Control Register */
+#define MAC_CR_RXALL 0x80000000
+/* TODO: delete this bit? It is not described in the data sheet. */
+#define MAC_CR_HBDIS 0x10000000
+#define MAC_CR_RCVOWN 0x00800000
+#define MAC_CR_LOOPBK 0x00200000
+#define MAC_CR_FDPX 0x00100000
+#define MAC_CR_MCPAS 0x00080000
+#define MAC_CR_PRMS 0x00040000
+#define MAC_CR_INVFILT 0x00020000
+#define MAC_CR_PASSBAD 0x00010000
+#define MAC_CR_HFILT 0x00008000
+#define MAC_CR_HPFILT 0x00002000
+#define MAC_CR_LCOLL 0x00001000
+#define MAC_CR_BCAST 0x00000800
+#define MAC_CR_DISRTY 0x00000400
+#define MAC_CR_PADSTR 0x00000100
+#define MAC_CR_BOLMT_MASK 0x000000C0
+#define MAC_CR_DFCHK 0x00000020
+#define MAC_CR_TXEN 0x00000008
+#define MAC_CR_RXEN 0x00000004
+
+#define ADDRH 0x02 /* R/W mask 0x0000FFFFUL */
+#define ADDRL 0x03 /* R/W mask 0xFFFFFFFFUL */
+#define HASHH 0x04 /* R/W */
+#define HASHL 0x05 /* R/W */
+
+#define MII_ACC 0x06 /* R/W */
+#define MII_ACC_PHY_ADDR 0x0000F800
+#define MII_ACC_MIIRINDA 0x000007C0
+#define MII_ACC_MII_WRITE 0x00000002
+#define MII_ACC_MII_BUSY 0x00000001
+
+#define MII_DATA 0x07 /* R/W mask 0x0000FFFFUL */
+
+#define FLOW 0x08 /* R/W */
+#define FLOW_FCPT 0xFFFF0000
+#define FLOW_FCPASS 0x00000004
+#define FLOW_FCEN 0x00000002
+#define FLOW_FCBSY 0x00000001
+
+#define VLAN1 0x09 /* R/W mask 0x0000FFFFUL */
+#define VLAN1_VTI1 0x0000ffff
+
+#define VLAN2 0x0A /* R/W mask 0x0000FFFFUL */
+#define VLAN2_VTI2 0x0000ffff
+
+#define WUFF 0x0B /* WO */
+
+#define WUCSR 0x0C /* R/W */
+#define WUCSR_GUE 0x00000200
+#define WUCSR_WUFR 0x00000040
+#define WUCSR_MPR 0x00000020
+#define WUCSR_WAKE_EN 0x00000004
+#define WUCSR_MPEN 0x00000002
+
+/* phy register offsets */
+#define PHY_BMCR 0x00
+#define PHY_BMSR 0x01
+#define PHY_PHYIDR1 0x02
+#define PHY_PHYIDR2 0x03
+#define PHY_ANAR 0x04
+#define PHY_ANLPAR 0x05
+#define PHY_ANER 0x06
+#define PHY_ANNPTR 0x07
+#define PHY_ANLPNP 0x08
+#define PHY_1000BTCR 0x09
+#define PHY_1000BTSR 0x0A
+#define PHY_EXSR 0x0F
+#define PHY_PHYSTS 0x10
+#define PHY_MIPSCR 0x11
+#define PHY_MIPGSR 0x12
+#define PHY_DCR 0x13
+#define PHY_FCSCR 0x14
+#define PHY_RECR 0x15
+#define PHY_PCSR 0x16
+#define PHY_LBR 0x17
+#define PHY_10BTSCR 0x18
+#define PHY_PHYCTRL 0x19
+
+/* PHY BMCR */
+#define PHY_BMCR_RESET 0x8000
+#define PHY_BMCR_LOOP 0x4000
+#define PHY_BMCR_100MB 0x2000
+#define PHY_BMCR_AUTON 0x1000
+#define PHY_BMCR_POWD 0x0800
+#define PHY_BMCR_ISO 0x0400
+#define PHY_BMCR_RST_NEG 0x0200
+#define PHY_BMCR_DPLX 0x0100
+#define PHY_BMCR_COL_TST 0x0080
+
+#define PHY_BMCR_SPEED_MASK 0x2040
+#define PHY_BMCR_1000_MBPS 0x0040
+#define PHY_BMCR_100_MBPS 0x2000
+#define PHY_BMCR_10_MBPS 0x0000
+
+/* phy BMSR */
+#define PHY_BMSR_100T4 0x8000
+#define PHY_BMSR_100TXF 0x4000
+#define PHY_BMSR_100TXH 0x2000
+#define PHY_BMSR_10TF 0x1000
+#define PHY_BMSR_10TH 0x0800
+#define PHY_BMSR_EXT_STAT 0x0100
+#define PHY_BMSR_PRE_SUP 0x0040
+#define PHY_BMSR_AUTN_COMP 0x0020
+#define PHY_BMSR_RF 0x0010
+#define PHY_BMSR_AUTN_ABLE 0x0008
+#define PHY_BMSR_LS 0x0004
+#define PHY_BMSR_JD 0x0002
+#define PHY_BMSR_EXT 0x0001
+
+/*phy ANLPAR */
+#define PHY_ANLPAR_NP 0x8000
+#define PHY_ANLPAR_ACK 0x4000
+#define PHY_ANLPAR_RF 0x2000
+#define PHY_ANLPAR_ASYMP 0x0800
+#define PHY_ANLPAR_PAUSE 0x0400
+#define PHY_ANLPAR_T4 0x0200
+#define PHY_ANLPAR_TXFD 0x0100
+#define PHY_ANLPAR_TX 0x0080
+#define PHY_ANLPAR_10FD 0x0040
+#define PHY_ANLPAR_10 0x0020
+#define PHY_ANLPAR_100 0x0380 /* we can run at 100 */
+/* phy ANLPAR 1000BASE-X */
+#define PHY_X_ANLPAR_NP 0x8000
+#define PHY_X_ANLPAR_ACK 0x4000
+#define PHY_X_ANLPAR_RF_MASK 0x3000
+#define PHY_X_ANLPAR_PAUSE_MASK 0x0180
+#define PHY_X_ANLPAR_HD 0x0040
+#define PHY_X_ANLPAR_FD 0x0020
+
+#define PHY_ANLPAR_PSB_MASK 0x001f
+#define PHY_ANLPAR_PSB_802_3 0x0001
+#define PHY_ANLPAR_PSB_802_9 0x0002
+
+/* phy 1000BTCR */
+#define PHY_1000BTCR_1000FD 0x0200
+#define PHY_1000BTCR_1000HD 0x0100
+
+/* phy 1000BTSR */
+#define PHY_1000BTSR_MSCF 0x8000
+#define PHY_1000BTSR_MSCR 0x4000
+#define PHY_1000BTSR_LRS 0x2000
+#define PHY_1000BTSR_RRS 0x1000
+#define PHY_1000BTSR_1000FD 0x0800
+#define PHY_1000BTSR_1000HD 0x0400
+
+/* phy EXSR */
+#define PHY_EXSR_1000XF 0x8000
+#define PHY_EXSR_1000XH 0x4000
+#define PHY_EXSR_1000TF 0x2000
+#define PHY_EXSR_1000TH 0x1000
+
+
+
+typedef struct {
+ VENDOR_DEVICE_PATH EthDevicePath;
+ EFI_DEVICE_PATH EndDevicePath;
+} ETH_DEVICE_PATH;
+
+//
+// Private data for driver.
+//
+#define ETH_DXE_PRIVATE_DATA_SIGNATURE SIGNATURE_32( 'E', 'T', 'H', 'D' )
+
+typedef struct
+{
+ UINT32 Signature;
+ EFI_SIMPLE_NETWORK_PROTOCOL Snp;
+ EFI_SIMPLE_NETWORK_MODE Mode;
+ ETH_DEVICE_PATH DevicePath;
+} ETH_DXE_PRIVATE_DATA;
+
+#define ETH_DXE_PRIVATE_DATA_FROM_SNP_THIS(a) \
+ CR( a, ETH_DXE_PRIVATE_DATA, Snp, ETH_DXE_PRIVATE_DATA_SIGNATURE )
+
+
+EFI_STATUS
+EFIAPI
+EthStart(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This
+);
+
+EFI_STATUS
+EFIAPI
+EthStop(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This
+);
+
+EFI_STATUS
+EFIAPI
+EthInitialize(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINTN ExtraRxBufferSize,
+ UINTN ExtraTxBufferSize
+);
+
+EFI_STATUS
+EFIAPI
+EthReset(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN ExtendedVerification
+);
+
+EFI_STATUS
+EFIAPI
+EthShutdown(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This
+);
+
+EFI_STATUS
+EFIAPI
+EthReceiveFilters(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINT32 Enable,
+ UINT32 Disable,
+ BOOLEAN ResetMCastFilter,
+ UINTN MCastFilterCnt,
+ EFI_MAC_ADDRESS *MCastFilter
+);
+
+EFI_STATUS
+EFIAPI
+EthStationAddress(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN Reset,
+ EFI_MAC_ADDRESS *New
+);
+
+EFI_STATUS
+EFIAPI
+EthStatistics(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN Reset,
+ UINTN *StatisticsSize,
+ EFI_NETWORK_STATISTICS *StatisticsTable
+);
+
+EFI_STATUS
+EFIAPI
+EthMCastIpToMac(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN IPv6,
+ EFI_IP_ADDRESS *IP,
+ EFI_MAC_ADDRESS *MAC
+);
+
+EFI_STATUS
+EFIAPI
+EthNvData(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ BOOLEAN ReadWrite,
+ UINTN Offset,
+ UINTN BufferSize,
+ VOID *Buffer
+);
+
+EFI_STATUS
+EFIAPI
+EthGetStatus(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINT32 *InterruptStatus,
+ VOID **TxBuf
+);
+
+EFI_STATUS
+EFIAPI
+EthTransmit(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINTN HeaderSize,
+ UINTN BufferSize,
+ VOID *Buffer,
+ EFI_MAC_ADDRESS *SrcAddr,
+ EFI_MAC_ADDRESS *DestAddr,
+ UINT16 *Protocol
+);
+
+EFI_STATUS
+EFIAPI
+EthReceive(
+ EFI_SIMPLE_NETWORK_PROTOCOL *This,
+ UINTN *HeaderSize,
+ UINTN *BufferSize,
+ VOID *Buffer,
+ EFI_MAC_ADDRESS *SrcAddr,
+ EFI_MAC_ADDRESS *DestAddr,
+ UINT16 *Protocol
+);
+
+#endif // _Eth_Dxe_H__
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.inf
new file mode 100644
index 000000000..e9f649e15
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/EthDxe/EthDxe.inf
@@ -0,0 +1,59 @@
+## @file
+#
+# Component description file for GraphicsConsole module
+#
+# This is the main routine for initializing the Graphics Console support routines.
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = EthDxe
+ FILE_GUID = 25ac458a-cf60-476e-861a-211c757657a6
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = EthDxeInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING =
+# COMPONENT_NAME =
+# COMPONENT_NAME2 =
+#
+
+[Sources]
+ EthDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos4210/ExynosPkg.dec
+ SamsungPlatformPkg/SamsungPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ IoLib
+ TimerLib
+
+[Protocols]
+ gEfiSimpleNetworkProtocolGuid ## TO_START
+
+[Guids]
+
+[Pcd]
+ gExynosPkgTokenSpaceGuid.PcdSMC911XBase
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390Gic.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390Gic.c
new file mode 100644
index 000000000..3224cbef9
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390Gic.c
@@ -0,0 +1,70 @@
+/** @file
+*
+* Copyright (c) 2011-2012, 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 <Uefi.h>
+#include <Library/IoLib.h>
+#include <Library/ArmGicLib.h>
+#include <Library/PcdLib.h>
+
+UINTN
+EFIAPI
+ArmGicGetMaxNumInterrupts (
+ IN INTN GicDistributorBase
+ )
+{
+ return 32 * ((MmioRead32 (GicDistributorBase + ARM_GIC_ICDICTR) & 0x1F) + 1);
+}
+
+VOID
+EFIAPI
+ArmGicSendSgiTo (
+ IN INTN GicDistributorBase,
+ IN INTN TargetListFilter,
+ IN INTN CPUTargetList,
+ IN INTN SgiId
+ )
+{
+ MmioWrite32 (GicDistributorBase + ARM_GIC_ICDSGIR, ((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId);
+}
+
+RETURN_STATUS
+EFIAPI
+ArmGicAcknowledgeInterrupt (
+ IN UINTN GicDistributorBase,
+ IN UINTN GicInterruptInterfaceBase,
+ OUT UINTN *CoreId,
+ OUT UINTN *InterruptId
+ )
+{
+ UINT32 Interrupt;
+
+ // Read the Interrupt Acknowledge Register
+ Interrupt = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR);
+
+ // Check if it is a valid interrupt ID
+ if ((Interrupt & 0x3FF) < ArmGicGetMaxNumInterrupts (GicDistributorBase)) {
+ // Got a valid SGI number hence signal End of Interrupt by writing to ICCEOIR
+ MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, Interrupt);
+
+ if (CoreId) {
+ *CoreId = (Interrupt >> 10) & 0x7;
+ }
+ if (InterruptId) {
+ *InterruptId = Interrupt & 0x3FF;
+ }
+ return RETURN_SUCCESS;
+ } else {
+ return RETURN_INVALID_PARAMETER;
+ }
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.c
new file mode 100644
index 000000000..4e2fc883d
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.c
@@ -0,0 +1,415 @@
+/*++
+
+Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
+Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
+Portions copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
+
+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.
+
+Module Name:
+
+ Gic.c
+
+Abstract:
+
+ Driver implementing the GIC interrupt controller protocol
+
+--*/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/ArmGicLib.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/HardwareInterrupt.h>
+
+#define ARM_GIC_DEFAULT_PRIORITY 0x80
+
+extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol;
+
+//
+// Notifications
+//
+EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
+
+// Maximum Number of Interrupts
+UINTN mGicNumInterrupts = 0;
+
+HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;
+
+/**
+ Register Handler for the specified interrupt source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+ @param Handler Callback for interrupt. NULL to unregister
+
+ @retval EFI_SUCCESS Source was updated to support Handler.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterInterruptSource (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN HARDWARE_INTERRUPT_HANDLER Handler
+ )
+{
+ if (Source > mGicNumInterrupts) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gRegisteredInterruptHandlers[Source] = Handler;
+
+ // If the interrupt handler is unregistered then disable the interrupt
+ if (NULL == Handler){
+ return This->DisableInterruptSource (This, Source);
+ } else {
+ return This->EnableInterruptSource (This, Source);
+ }
+}
+
+/**
+ Enable interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt enabled.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableInterruptSource (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ )
+{
+ UINT32 RegOffset;
+ UINTN RegShift;
+
+ if (Source > mGicNumInterrupts) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ // calculate enable register offset and bit position
+ RegOffset = Source / 32;
+ RegShift = Source % 32;
+
+ // write set-enable register
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset), 1 << RegShift);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt disabled.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableInterruptSource (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ )
+{
+ UINT32 RegOffset;
+ UINTN RegShift;
+
+ if (Source > mGicNumInterrupts) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ // Calculate enable register offset and bit position
+ RegOffset = Source / 32;
+ RegShift = Source % 32;
+
+ // Write set-enable register
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDICER + (4*RegOffset), 1 << RegShift);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return current state of interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+ @param InterruptState TRUE: source enabled, FALSE: source disabled.
+
+ @retval EFI_SUCCESS InterruptState is valid
+ @retval EFI_DEVICE_ERROR InterruptState is not valid
+
+**/
+EFI_STATUS
+EFIAPI
+GetInterruptSourceState (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN BOOLEAN *InterruptState
+ )
+{
+ UINT32 RegOffset;
+ UINTN RegShift;
+
+ if (Source > mGicNumInterrupts) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ // calculate enable register offset and bit position
+ RegOffset = Source / 32;
+ RegShift = Source % 32;
+
+ if ((MmioRead32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset)) & (1<<RegShift)) == 0) {
+ *InterruptState = FALSE;
+ } else {
+ *InterruptState = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Signal to the hardware that the End Of Intrrupt state
+ has been reached.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt EOI'ed.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+EndOfInterrupt (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ )
+{
+ if (Source > mGicNumInterrupts) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCEIOR, Source);
+ return EFI_SUCCESS;
+}
+
+/**
+ EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
+
+ @param InterruptType Defines the type of interrupt or exception that
+ occurred on the processor.This parameter is processor architecture specific.
+ @param SystemContext A pointer to the processor context when
+ the interrupt occurred on the processor.
+
+ @return None
+
+**/
+VOID
+EFIAPI
+IrqInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 GicInterrupt;
+ HARDWARE_INTERRUPT_HANDLER InterruptHandler;
+
+ GicInterrupt = MmioRead32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCIAR);
+
+ // Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the number of interrupt (ie: Spurious interrupt).
+ if (GicInterrupt >= mGicNumInterrupts) {
+ // The special interrupt do not need to be acknowledge
+ return;
+ }
+
+ InterruptHandler = gRegisteredInterruptHandlers[GicInterrupt];
+ if (InterruptHandler != NULL) {
+ // Call the registered interrupt handler.
+ InterruptHandler (GicInterrupt, SystemContext);
+ } else {
+ DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
+ }
+
+ EndOfInterrupt (&gHardwareInterruptProtocol, GicInterrupt);
+}
+
+//
+// Making this global saves a few bytes in image size
+//
+EFI_HANDLE gHardwareInterruptHandle = NULL;
+
+//
+// The protocol instance produced by this driver
+//
+EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {
+ RegisterInterruptSource,
+ EnableInterruptSource,
+ DisableInterruptSource,
+ GetInterruptSourceState,
+ EndOfInterrupt
+};
+
+/**
+ Shutdown our hardware
+
+ DXE Core will disable interrupts and turn off the timer and disable interrupts
+ after all the event handlers have run.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+ExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Index;
+
+ // Acknowledge all pending interrupts
+ for (Index = 0; Index < mGicNumInterrupts; Index++) {
+ DisableInterruptSource (&gHardwareInterruptProtocol, Index);
+ }
+
+ for (Index = 0; Index < mGicNumInterrupts; Index++) {
+ EndOfInterrupt (&gHardwareInterruptProtocol, Index);
+ }
+
+ // Disable Gic Interface
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x0);
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0x0);
+
+ // Disable Gic Distributor
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x0);
+}
+
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+InterruptDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINT32 RegOffset;
+ UINTN RegShift;
+ EFI_CPU_ARCH_PROTOCOL *Cpu;
+
+ // Make sure the Interrupt Controller Protocol is not already installed in the system.
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
+
+ mGicNumInterrupts = ArmGicGetMaxNumInterrupts (PcdGet32(PcdGicDistributorBase));
+
+ for (Index = 0; Index < mGicNumInterrupts; Index++) {
+ DisableInterruptSource (&gHardwareInterruptProtocol, Index);
+
+ // Set Priority
+ RegOffset = Index / 4;
+ RegShift = (Index % 4) * 8;
+ MmioAndThenOr32 (
+ PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPR + (4*RegOffset),
+ ~(0xff << RegShift),
+ ARM_GIC_DEFAULT_PRIORITY << RegShift
+ );
+ }
+
+ // Configure interrupts for cpu 0
+ for (Index = 0; Index < (mGicNumInterrupts / 4); Index++) {
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPTR + (Index*4), 0x01010101);
+ }
+
+ // Set binary point reg to 0x7 (no preemption)
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCBPR, 0x7);
+
+ // Set priority mask reg to 0xff to allow all priorities through
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0xF0);
+
+ // Enable gic cpu interface
+ MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x1);
+
+ // Enable gic distributor
+ MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x3);
+
+ // Initialize the array for the Interrupt Handlers
+ gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gHardwareInterruptHandle,
+ &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get the CPU protocol that this driver requires.
+ //
+ Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Unregister the default exception handler.
+ //
+ Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register to receive interrupts
+ //
+ Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);
+ ASSERT_EFI_ERROR(Status);
+
+ // Register for an ExitBootServicesEvent
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.inf
new file mode 100644
index 000000000..723931522
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.inf
@@ -0,0 +1,54 @@
+#/** @file
+#
+# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2012, ARM Ltd. All rights reserved.<BR>
+#
+# 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 = PL390GicDxe
+ FILE_GUID = DE371F7C-DEC4-4D21-ADF1-593ABCC15882
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InterruptDxeInitialize
+
+
+[Sources.common]
+ PL390Gic.c
+ PL390GicDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ DebugLib
+ PrintLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ IoLib
+
+[Protocols]
+ gHardwareInterruptProtocolGuid
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd.common]
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+
+[Depex]
+ gEfiCpuArchProtocolGuid
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicLib.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicLib.inf
new file mode 100644
index 000000000..615b41039
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicLib.inf
@@ -0,0 +1,28 @@
+#/* @file
+# Copyright (c) 2011-2012, 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 = PL390GicLib
+ FILE_GUID = 03d05ee4-cdeb-458c-9dfc-993f09bdf405
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmGicLib
+
+[Sources]
+ PL390Gic.c
+ PL390GicNonSec.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicNonSec.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicNonSec.c
new file mode 100644
index 000000000..10fcb4e5e
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicNonSec.c
@@ -0,0 +1,44 @@
+/** @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 <Uefi.h>
+#include <Library/IoLib.h>
+#include <Library/ArmGicLib.h>
+
+
+VOID
+EFIAPI
+ArmGicEnableInterruptInterface (
+ IN INTN GicInterruptInterfaceBase
+ )
+{
+ /*
+ * Enable the CPU interface in Non-Secure world
+ * Note: The ICCICR register is banked when Security extensions are implemented
+ */
+ MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, 0x1);
+}
+
+VOID
+EFIAPI
+ArmGicEnableDistributor (
+ IN INTN GicDistributorBase
+ )
+{
+ /*
+ * Enable GIC distributor in Non-Secure world.
+ * Note: The ICDDCR register is banked when Security extensions are implemented
+ */
+ MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x1);
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSec.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSec.c
new file mode 100644
index 000000000..82ecfde6e
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSec.c
@@ -0,0 +1,119 @@
+/** @file
+*
+* Copyright (c) 2011-2012, 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 <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <Library/IoLib.h>
+#include <Library/ArmGicLib.h>
+
+/*
+ * This function configures the all interrupts to be Non-secure.
+ *
+ */
+VOID
+EFIAPI
+ArmGicSetupNonSecure (
+ IN UINTN MpId,
+ IN INTN GicDistributorBase,
+ IN INTN GicInterruptInterfaceBase
+ )
+{
+ UINTN InterruptId;
+ UINTN CachedPriorityMask;
+ UINTN Index;
+
+ CachedPriorityMask = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR);
+
+ // Set priority Mask so that no interrupts get through to CPU
+ MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0);
+
+ // Check if there are any pending interrupts
+ //TODO: could be extended to take Peripheral interrupts into consideration, but at the moment only SGI's are taken into consideration.
+ while(0 != (MmioRead32 (GicDistributorBase + ARM_GIC_ICDICPR) & 0xF)) {
+ // Some of the SGI's are still pending, read Ack register and send End of Interrupt Signal
+ InterruptId = MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR);
+
+ // Write to End of interrupt signal
+ MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, InterruptId);
+ }
+
+ // Only the primary core should set the Non Secure bit to the SPIs (Shared Peripheral Interrupt).
+ if (ArmPlatformIsPrimaryCore (MpId)) {
+ // Ensure all GIC interrupts are Non-Secure
+ for (Index = 0; Index < (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32); Index++) {
+ MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), 0xffffffff);
+ }
+ } else {
+ // The secondary cores only set the Non Secure bit to their banked PPIs
+ MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR, 0xffffffff);
+ }
+
+ // Ensure all interrupts can get through the priority mask
+ MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, CachedPriorityMask);
+}
+
+/*
+ * This function configures the interrupts set by the mask to be secure.
+ *
+ */
+VOID
+EFIAPI
+ArmGicSetSecureInterrupts (
+ IN UINTN GicDistributorBase,
+ IN UINTN* GicSecureInterruptMask,
+ IN UINTN GicSecureInterruptMaskSize
+ )
+{
+ UINTN Index;
+ UINT32 InterruptStatus;
+
+ // We must not have more interrupts defined by the mask than the number of available interrupts
+ ASSERT(GicSecureInterruptMaskSize <= (ArmGicGetMaxNumInterrupts (GicDistributorBase) / 32));
+
+ // Set all the interrupts defined by the mask as Secure
+ for (Index = 0; Index < GicSecureInterruptMaskSize; Index++) {
+ InterruptStatus = MmioRead32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4));
+ MmioWrite32 (GicDistributorBase + ARM_GIC_ICDISR + (Index * 4), InterruptStatus & (~GicSecureInterruptMask[Index]));
+ }
+}
+
+VOID
+EFIAPI
+ArmGicEnableInterruptInterface (
+ IN INTN GicInterruptInterfaceBase
+ )
+{
+ // Set Priority Mask to allow interrupts
+ MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x000000F0);
+
+ // Enable CPU interface in Secure world
+ // Enable CPU inteface in Non-secure World
+ // Signal Secure Interrupts to CPU using FIQ line *
+ MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR,
+ ARM_GIC_ICCICR_ENABLE_SECURE |
+ ARM_GIC_ICCICR_ENABLE_NS |
+ ARM_GIC_ICCICR_SIGNAL_SECURE_TO_FIQ);
+}
+
+VOID
+EFIAPI
+ArmGicEnableDistributor (
+ IN INTN GicDistributorBase
+ )
+{
+ // Turn on the GIC distributor
+ MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 1);
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSecLib.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSecLib.inf
new file mode 100644
index 000000000..ab399b4fb
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSecLib.inf
@@ -0,0 +1,37 @@
+#/* @file
+# Copyright (c) 2011-2012, 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 = PL390GicSecLib
+ FILE_GUID = 85f3cf80-b5f4-11df-9855-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmGicLib
+
+[Sources]
+ PL390Gic.c
+ PL390GicSec.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmLib
+ DebugLib
+ IoLib
+ PcdLib
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.c
new file mode 100644
index 000000000..cdd4102e5
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.c
@@ -0,0 +1,177 @@
+/** @file
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/ExynosGpio.h>
+#include <Platform/ArmPlatform.h>
+#include <Library/ExynosLib.h>
+
+
+
+EFI_STATUS
+Get (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ OUT UINTN *Value
+ )
+{
+ UINTN Port;
+ UINTN Pin;
+ UINT32 DataInRegister;
+
+ if (Value == NULL)
+ {
+ return EFI_UNSUPPORTED;
+ }
+
+ Port = GPIO_PORT(Gpio);
+ Pin = GPIO_PIN(Gpio);
+
+ DataInRegister = GpioBase(Port) + GPIO_DATAIN;
+
+ if (MmioRead32 (DataInRegister) & GPIO_DATAIN_MASK(Pin)) {
+ *Value = 1;
+ } else {
+ *Value = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Set (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ IN EXYNOS_GPIO_MODE Mode
+ )
+{
+ UINTN Port;
+ UINTN Pin;
+ UINT32 OutputRegister;
+
+ Port = GPIO_PORT(Gpio);
+ Pin = GPIO_PIN(Gpio);
+ OutputRegister = GpioBase(Port) + GPIO_CON;
+ DEBUG ((EFI_D_INFO, "Gpio->Set: Gpio(0x%x), Port (0x%x), Pin (0x%x), Register (0x%x).\n", Gpio, Port, Pin, OutputRegister));
+ switch (Mode)
+ {
+ case GPIO_MODE_INPUT:
+ break;
+ case GPIO_MODE_OUTPUT_0:
+ MmioAndThenOr32(OutputRegister, ~GPIO_SFN_MASK(Pin), GPIO_OP_EN(Pin));
+ MmioAndThenOr32((GpioBase(Port) + GPIO_DATAIN), ~GPIO_DATAIN_MASK(Pin), GPIO_DATA_LOW(Pin));
+ break;
+ case GPIO_MODE_OUTPUT_1:
+ MmioAndThenOr32(OutputRegister, ~GPIO_SFN_MASK(Pin), GPIO_OP_EN(Pin));
+ MmioAndThenOr32((GpioBase(Port) + GPIO_DATAIN), ~GPIO_DATAIN_MASK(Pin), GPIO_DATA_HIGH(Pin));
+ break;
+ case GPIO_MODE_SPECIAL_FUNCTION_2:
+ MmioAndThenOr32(OutputRegister, ~GPIO_SFN_MASK(Pin), GPIO_SFN_EN(Pin));
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetMode (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ OUT EXYNOS_GPIO_MODE *Mode
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+SetPull (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ IN EXYNOS_GPIO_PULL Direction
+ )
+{
+ UINTN Port;
+ UINTN Pin;
+ UINT32 OutputRegister;
+
+ Port = GPIO_PORT(Gpio);
+ Pin = GPIO_PIN(Gpio);
+ OutputRegister = GpioBase(Port) + GPIO_PUD;
+ DEBUG ((EFI_D_INFO, "Gpio->SetPull: Gpio(0x%x), Port (0x%x), Pin (0x%x), Register (0x%x).\n", Gpio, Port, Pin, OutputRegister));
+ switch (Direction)
+ {
+ case GPIO_PULL_NONE:
+ MmioAndThenOr32(OutputRegister, ~GPIO_PUD_MASK(Pin), GPIO_PUD_DIS(Pin));
+ break;
+ case GPIO_PULL_UP:
+ MmioAndThenOr32(OutputRegister, ~GPIO_PUD_MASK(Pin), GPIO_PUP_EN(Pin));
+ break;
+ case GPIO_PULL_DOWN:
+ MmioAndThenOr32(OutputRegister, ~GPIO_PUD_MASK(Pin), GPIO_PDN_EN(Pin));
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+SetStrength (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ IN EXYNOS_GPIO_STRN Strength
+ )
+{
+ UINTN Port;
+ UINTN Pin;
+ UINT32 OutputRegister;
+
+ Port = GPIO_PORT(Gpio);
+ Pin = GPIO_PIN(Gpio);
+ OutputRegister = GpioBase(Port) + GPIO_DRV;
+ MmioAndThenOr32(OutputRegister, ~GPIO_DRV_MASK(Pin), GPIO_DRV_SET(Strength,Pin));
+
+ return EFI_SUCCESS;
+}
+
+
+
+EXYNOS_GPIO Gpio = {
+ Get,
+ Set,
+ GetMode,
+ SetPull,
+ SetStrength
+};
+
+EFI_STATUS
+GpioInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, &gSamsungPlatformGpioProtocolGuid, &Gpio, NULL);
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.inf
new file mode 100644
index 000000000..605b80576
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.inf
@@ -0,0 +1,46 @@
+#/** @file
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = Gpio
+ FILE_GUID = E7D9CAE1-6930-46E3-BDF9-0027446E7DF2
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = GpioInitialize
+
+
+[Sources.common]
+ Gpio.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+ SamsungPlatformPkg/SamsungPlatformPkg.dec
+
+[LibraryClasses]
+ IoLib
+ UefiDriverEntryPoint
+ ExynosLib
+ DebugLib
+
+[Guids]
+
+[Protocols]
+ gSamsungPlatformGpioProtocolGuid
+
+[Pcd]
+
+[depex]
+ TRUE
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.c
new file mode 100644
index 000000000..75ffc2668
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.c
@@ -0,0 +1,241 @@
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/ArmGicLib.h>
+#include <Library/UncachedMemoryAllocationLib.h>
+
+#include <Protocol/Hash.h>
+
+#include <Platform/ArmPlatform.h>
+#include <Platform/Exynos5250.h>
+
+#include "HashDxe.h"
+
+#define CLOCK_ON 1
+#define CLOCK_OFF 0
+
+EFI_STATUS
+EFIAPI
+CryptoClockGating (
+ IN UINT32 clock_status
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 CmuBase;
+ UINT32 value;
+
+ CmuBase = PcdGet32(PcdCmuBase);
+ value = MmioRead32(CmuBase + SSS_CMU_OFFSET);
+
+ if (clock_status == CLOCK_ON)
+ MmioWrite32(CmuBase + SSS_CMU_OFFSET, value | CLK_SSS);
+ else if (clock_status == CLOCK_OFF)
+ MmioWrite32(CmuBase + SSS_CMU_OFFSET, value & ~CLK_SSS);
+ else {
+ DEBUG((EFI_D_ERROR, "[HashDxe] : Unsupported SSS clock status\n"));
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/**
+ Returns the size of the hash which results from a specific algorithm.
+
+ @param[in] This Points to this instance of EFI_HASH_PROTOCOL.
+ @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
+ @param[out] HashSize Holds the returned size of the algorithm's hash.
+
+ @retval EFI_SUCCESS Hash size returned successfully.
+ @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported
+ by this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+HashDxeGetHashSize (
+ IN CONST EFI_HASH_PROTOCOL *This,
+ IN CONST EFI_GUID *HashAlgorithm,
+ OUT UINTN *HashSize
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if (CompareGuid(HashAlgorithm, &gEfiHashAlgorithmSha1Guid))
+ *HashSize = sizeof(EFI_SHA1_HASH);
+ else if (CompareGuid(HashAlgorithm, &gEfiHashAlgorithmSha256Guid))
+ *HashSize = sizeof(EFI_SHA256_HASH);
+ else {
+ DEBUG((EFI_D_ERROR, "[HashDxe] : Unsupported Hash Algorithm\n"));
+ Status = EFI_UNSUPPORTED;
+ }
+
+ return Status;
+}
+
+/**
+ Returns the size of the hash which results from a specific algorithm.
+
+ @param[in] This Points to this instance of EFI_HASH_PROTOCOL.
+ @param[in] HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use.
+ @param[in] Extend Specifies whether to create a new hash (FALSE) or extend the specified
+ existing hash (TRUE).
+ @param[in] Message Points to the start of the message.
+ @param[in] MessageSize The size of Message, in bytes.
+ @param[in,out] Hash On input, if Extend is TRUE, then this holds the hash to extend. On
+ output, holds the resulting hash computed from the message.
+
+ @retval EFI_SUCCESS Hash returned successfully.
+ @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this
+ driver. Or, Extend is TRUE, and the algorithm doesn't support extending the hash.
+
+**/
+EFI_STATUS
+EFIAPI
+HashDxeRunHash (
+ IN CONST EFI_HASH_PROTOCOL *This,
+ IN CONST EFI_GUID *HashAlgorithm,
+ IN BOOLEAN Extend,
+ IN CONST UINT8 *Message,
+ IN UINT64 MessageSize,
+ IN OUT EFI_HASH_OUTPUT *Hash
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 value;
+ UINT32 CryptoBase;
+ UINT32 TotalMessageSize;
+ UINT32 HashResult[8];
+ UINT8 *TempMessage;
+
+ CryptoBase = PcdGet32(PcdCryptoBase);
+
+ CryptoClockGating(CLOCK_ON);
+
+ /* Flush HRDMA */
+ MmioWrite32(CryptoBase + SSS_FC_HRDMAC, SSS_FC_HRDMACFLUSH_ON);
+ MmioWrite32(CryptoBase + SSS_FC_HRDMAC, SSS_FC_HRDMACFLUSH_OFF);
+
+ /* Set byte swap of in/out data and iv */
+ MmioWrite32(CryptoBase + SSS_HASH_BYTESWAP,
+ SSS_HASH_SWAPDI_ON | SSS_HASH_SWAPDO_ON | SSS_HASH_SWAPIV_ON);
+
+ /* Select HASH input mux as external source */
+ value = MmioRead32(CryptoBase + SSS_FC_FIFOCTRL);
+ value = (value & ~SSS_FC_SELHASH_MASK) | SSS_FC_SELHASH_EXOUT;
+ MmioWrite32(CryptoBase + SSS_FC_FIFOCTRL, value);
+
+ /* Set HASH algorithm and start hash engine */
+ if (CompareGuid(HashAlgorithm, &gEfiHashAlgorithmSha1Guid))
+ value = SSS_HASH_ENGSEL_SHA1HASH | SSS_HASH_STARTBIT_ON;
+ else if (CompareGuid(HashAlgorithm, &gEfiHashAlgorithmSha256Guid))
+ value = SSS_HASH_ENGSEL_SHA256HASH | SSS_HASH_STARTBIT_ON;
+ else {
+ DEBUG((EFI_D_ERROR, "[HashDxe] : Unsupported Hash Algorithm\n"));
+ Status = EFI_UNSUPPORTED;
+ return Status;
+ }
+ MmioWrite32(CryptoBase + SSS_HASH_CONTROL, value);
+
+ /* Enable FIFO mode */
+ MmioWrite32(CryptoBase + SSS_HASH_FIFO_MODE, SSS_HASH_FIFO_ON);
+
+ if (Extend == 0)
+ TotalMessageSize = MessageSize;
+ else if (Extend == 1) {
+ if (CompareGuid(HashAlgorithm, &gEfiHashAlgorithmSha1Guid)) {
+ TempMessage = (UINT8 *)UncachedAllocatePool(sizeof(EFI_SHA1_HASH) + MessageSize);
+ CopyMem(TempMessage, Hash, sizeof(EFI_SHA1_HASH));
+ CopyMem(TempMessage + sizeof(EFI_SHA1_HASH), Message, MessageSize);
+ TotalMessageSize = sizeof(EFI_SHA1_HASH) + MessageSize;
+ } else if (CompareGuid(HashAlgorithm, &gEfiHashAlgorithmSha256Guid)) {
+ TempMessage = (UINT8 *)UncachedAllocatePool(sizeof(EFI_SHA256_HASH) + MessageSize);
+ CopyMem(TempMessage, Hash, sizeof(EFI_SHA256_HASH));
+ CopyMem(TempMessage + sizeof(EFI_SHA256_HASH), Message, MessageSize);
+ TotalMessageSize = sizeof(EFI_SHA256_HASH) + MessageSize;
+ }
+ }
+
+ MmioWrite32(CryptoBase + SSS_HASH_MSGSIZE_LOW, TotalMessageSize);
+ MmioWrite32(CryptoBase + SSS_HASH_MSGSIZE_HIGH, 0);
+
+ /* Set HRDMA */
+ /*
+ * Message must be a physical address. Check it.
+ */
+ if (Extend == 0)
+ MmioWrite32(CryptoBase + SSS_FC_HRDMAS, (UINT32)Message);
+ else if (Extend == 1)
+ MmioWrite32(CryptoBase + SSS_FC_HRDMAS, (UINT32)TempMessage);
+
+ MmioWrite32(CryptoBase + SSS_FC_HRDMAL, TotalMessageSize);
+
+ /* Check the HASH status */
+ while ((MmioRead32(CryptoBase + SSS_HASH_STATUS) & SSS_HASH_MSGDONE_MASK)
+ == SSS_HASH_MSGDONE_OFF);
+
+ /* Clear MSG_DONE bit */
+ MmioWrite32(CryptoBase + SSS_HASH_STATUS, SSS_HASH_MSGDONE_ON);
+
+ /* Read hash result */
+ HashResult[0] = MmioRead32(CryptoBase + SSS_HASH_RESULT1);
+ HashResult[1] = MmioRead32(CryptoBase + SSS_HASH_RESULT2);
+ HashResult[2] = MmioRead32(CryptoBase + SSS_HASH_RESULT3);
+ HashResult[3] = MmioRead32(CryptoBase + SSS_HASH_RESULT4);
+ HashResult[4] = MmioRead32(CryptoBase + SSS_HASH_RESULT5);
+
+ if (CompareGuid(HashAlgorithm, &gEfiHashAlgorithmSha256Guid)) {
+ HashResult[5] = MmioRead32(CryptoBase + SSS_HASH_RESULT6);
+ HashResult[6] = MmioRead32(CryptoBase + SSS_HASH_RESULT7);
+ HashResult[7] = MmioRead32(CryptoBase + SSS_HASH_RESULT8);
+ }
+
+ if (CompareGuid(HashAlgorithm, &gEfiHashAlgorithmSha1Guid))
+ CopyMem(Hash, HashResult, sizeof(EFI_SHA1_HASH));
+ else if (CompareGuid(HashAlgorithm, &gEfiHashAlgorithmSha256Guid))
+ CopyMem(Hash, HashResult, sizeof(EFI_SHA256_HASH));
+ else {
+ DEBUG((EFI_D_ERROR, "[HashDxe] : Unsupported Hash Algorithm\n"));
+ Status = EFI_UNSUPPORTED;
+ return Status;
+ }
+
+ MmioWrite32(CryptoBase + SSS_FC_INTPEND, SSS_FC_HRDMA);
+
+ return Status;
+}
+
+EFI_HASH_PROTOCOL gHash = {
+ HashDxeGetHashSize,
+ HashDxeRunHash
+};
+
+/**
+ Initialize the state information for the HashDxe
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+HashDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &ImageHandle,
+ &gEfiHashProtocolGuid,
+ &gHash,
+ NULL
+ );
+
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.h
new file mode 100644
index 000000000..6a2562916
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.h
@@ -0,0 +1,417 @@
+/** @file
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 _CRYPTODXE_H_
+#define _CRYPTODXE_H_
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+
+#define SSS_CMU_OFFSET (0x8800)
+#define CLK_SSS (1 << 2)
+
+#define SSS_FC_OFFSET (0x0)
+#define SSS_AES_OFFSET (0x200)
+#define SSS_HASH_OFFSET (0x400)
+
+/* Feed control registers */
+#define SSS_FC_INTSTAT (SSS_FC_OFFSET + 0x00)
+#define SSS_FC_INTENSET (SSS_FC_OFFSET + 0x04)
+#define SSS_FC_INTENCLR (SSS_FC_OFFSET + 0x08)
+#define SSS_FC_INTPEND (SSS_FC_OFFSET + 0x0C)
+#define SSS_FC_FIFOSTAT (SSS_FC_OFFSET + 0x10)
+#define SSS_FC_FIFOCTRL (SSS_FC_OFFSET + 0x14)
+#define SSS_FC_GLOBAL (SSS_FC_OFFSET + 0x18)
+#define SSS_FC_BRDMAS (SSS_FC_OFFSET + 0x20)
+#define SSS_FC_BRDMAL (SSS_FC_OFFSET + 0x24)
+#define SSS_FC_BRDMAC (SSS_FC_OFFSET + 0x28)
+#define SSS_FC_BTDMAS (SSS_FC_OFFSET + 0x30)
+#define SSS_FC_BTDMAL (SSS_FC_OFFSET + 0x34)
+#define SSS_FC_BTDMAC (SSS_FC_OFFSET + 0x38)
+#define SSS_FC_HRDMAS (SSS_FC_OFFSET + 0x40)
+#define SSS_FC_HRDMAL (SSS_FC_OFFSET + 0x44)
+#define SSS_FC_HRDMAC (SSS_FC_OFFSET + 0x48)
+#define SSS_FC_PKDMAS (SSS_FC_OFFSET + 0x50)
+#define SSS_FC_PKDMAL (SSS_FC_OFFSET + 0x54)
+#define SSS_FC_PKDMAC (SSS_FC_OFFSET + 0x58)
+#define SSS_FC_PKDMAO (SSS_FC_OFFSET + 0x5C)
+
+/* AES control registers */
+#define SSS_AES_CONTROL (SSS_AES_OFFSET + 0x00)
+#define SSS_AES_STATUS (SSS_AES_OFFSET + 0x04)
+
+#define SSS_AES_IN1 (SSS_AES_OFFSET + 0x10)
+#define SSS_AES_IN2 (SSS_AES_OFFSET + 0x14)
+#define SSS_AES_IN3 (SSS_AES_OFFSET + 0x18)
+#define SSS_AES_IN4 (SSS_AES_OFFSET + 0x1C)
+
+#define SSS_AES_OUT1 (SSS_AES_OFFSET + 0x20)
+#define SSS_AES_OUT2 (SSS_AES_OFFSET + 0x24)
+#define SSS_AES_OUT3 (SSS_AES_OFFSET + 0x28)
+#define SSS_AES_OUT4 (SSS_AES_OFFSET + 0x2C)
+
+#define SSS_AES_IV1 (SSS_AES_OFFSET + 0x30)
+#define SSS_AES_IV2 (SSS_AES_OFFSET + 0x34)
+#define SSS_AES_IV3 (SSS_AES_OFFSET + 0x38)
+#define SSS_AES_IV4 (SSS_AES_OFFSET + 0x3C)
+
+#define SSS_AES_CNT1 (SSS_AES_OFFSET + 0x40)
+#define SSS_AES_CNT2 (SSS_AES_OFFSET + 0x44)
+#define SSS_AES_CNT3 (SSS_AES_OFFSET + 0x48)
+#define SSS_AES_CNT4 (SSS_AES_OFFSET + 0x4C)
+
+#define SSS_AES_KEY1 (SSS_AES_OFFSET + 0x80)
+#define SSS_AES_KEY2 (SSS_AES_OFFSET + 0x84)
+#define SSS_AES_KEY3 (SSS_AES_OFFSET + 0x88)
+#define SSS_AES_KEY4 (SSS_AES_OFFSET + 0x8C)
+#define SSS_AES_KEY5 (SSS_AES_OFFSET + 0x90)
+#define SSS_AES_KEY6 (SSS_AES_OFFSET + 0x94)
+#define SSS_AES_KEY7 (SSS_AES_OFFSET + 0x98)
+#define SSS_AES_KEY8 (SSS_AES_OFFSET + 0x9C)
+
+/* TDES control registers */
+#define SSS_TDES_CONTROL (SSS_TDES_OFFSET + 0x00)
+#define SSS_TDES_STATUS (SSS_TDES_OFFSET + 0x04)
+
+#define SSS_TDES_KEY11 (SSS_TDES_OFFSET + 0x10)
+#define SSS_TDES_KEY12 (SSS_TDES_OFFSET + 0x14)
+#define SSS_TDES_KEY21 (SSS_TDES_OFFSET + 0x18)
+#define SSS_TDES_KEY22 (SSS_TDES_OFFSET + 0x1C)
+#define SSS_TDES_KEY31 (SSS_TDES_OFFSET + 0x20)
+#define SSS_TDES_KEY32 (SSS_TDES_OFFSET + 0x24)
+
+#define SSS_TDES_IV1 (SSS_TDES_OFFSET + 0x28)
+#define SSS_TDES_IV2 (SSS_TDES_OFFSET + 0x2C)
+
+#define SSS_TDES_IN1 (SSS_TDES_OFFSET + 0x30)
+#define SSS_TDES_IN2 (SSS_TDES_OFFSET + 0x34)
+
+#define SSS_TDES_OUT1 (SSS_TDES_OFFSET + 0x38)
+#define SSS_TDES_OUT2 (SSS_TDES_OFFSET + 0x3C)
+
+/* HASH control registers */
+#define SSS_HASH_CONTROL (SSS_HASH_OFFSET + 0x00)
+#define SSS_HASH_CONTROL2 (SSS_HASH_OFFSET + 0x04)
+#define SSS_HASH_FIFO_MODE (SSS_HASH_OFFSET + 0x08)
+#define SSS_HASH_BYTESWAP (SSS_HASH_OFFSET + 0x0C)
+#define SSS_HASH_STATUS (SSS_HASH_OFFSET + 0x10)
+#define SSS_HASH_MSGSIZE_LOW (SSS_HASH_OFFSET + 0x20)
+#define SSS_HASH_MSGSIZE_HIGH (SSS_HASH_OFFSET + 0x24)
+#define SSS_HASH_PRELEN_LOW (SSS_HASH_OFFSET + 0x28)
+#define SSS_HASH_PRELEN_HIGH (SSS_HASH_OFFSET + 0x2C)
+
+#define SSS_HASH_IN1 (SSS_HASH_OFFSET + 0x30)
+#define SSS_HASH_IN2 (SSS_HASH_OFFSET + 0x34)
+#define SSS_HASH_IN3 (SSS_HASH_OFFSET + 0x38)
+#define SSS_HASH_IN4 (SSS_HASH_OFFSET + 0x3C)
+#define SSS_HASH_IN5 (SSS_HASH_OFFSET + 0x40)
+#define SSS_HASH_IN6 (SSS_HASH_OFFSET + 0x44)
+#define SSS_HASH_IN7 (SSS_HASH_OFFSET + 0x48)
+#define SSS_HASH_IN8 (SSS_HASH_OFFSET + 0x4C)
+#define SSS_HASH_IN9 (SSS_HASH_OFFSET + 0x50)
+#define SSS_HASH_IN10 (SSS_HASH_OFFSET + 0x54)
+#define SSS_HASH_IN11 (SSS_HASH_OFFSET + 0x58)
+#define SSS_HASH_IN12 (SSS_HASH_OFFSET + 0x5C)
+#define SSS_HASH_IN13 (SSS_HASH_OFFSET + 0x60)
+#define SSS_HASH_IN14 (SSS_HASH_OFFSET + 0x64)
+#define SSS_HASH_IN15 (SSS_HASH_OFFSET + 0x68)
+#define SSS_HASH_IN16 (SSS_HASH_OFFSET + 0x6C)
+
+#define SSS_HASH_HMAC_KEY_IN1 (SSS_HASH_OFFSET + 0x70)
+#define SSS_HASH_HMAC_KEY_IN2 (SSS_HASH_OFFSET + 0x74)
+#define SSS_HASH_HMAC_KEY_IN3 (SSS_HASH_OFFSET + 0x78)
+#define SSS_HASH_HMAC_KEY_IN4 (SSS_HASH_OFFSET + 0x7C)
+#define SSS_HASH_HMAC_KEY_IN5 (SSS_HASH_OFFSET + 0x80)
+#define SSS_HASH_HMAC_KEY_IN6 (SSS_HASH_OFFSET + 0x84)
+#define SSS_HASH_HMAC_KEY_IN7 (SSS_HASH_OFFSET + 0x88)
+#define SSS_HASH_HMAC_KEY_IN8 (SSS_HASH_OFFSET + 0x8C)
+#define SSS_HASH_HMAC_KEY_IN9 (SSS_HASH_OFFSET + 0x90)
+#define SSS_HASH_HMAC_KEY_IN10 (SSS_HASH_OFFSET + 0x94)
+#define SSS_HASH_HMAC_KEY_IN11 (SSS_HASH_OFFSET + 0x98)
+#define SSS_HASH_HMAC_KEY_IN12 (SSS_HASH_OFFSET + 0x9C)
+#define SSS_HASH_HMAC_KEY_IN13 (SSS_HASH_OFFSET + 0xA0)
+#define SSS_HASH_HMAC_KEY_IN14 (SSS_HASH_OFFSET + 0xA4)
+#define SSS_HASH_HMAC_KEY_IN15 (SSS_HASH_OFFSET + 0xA8)
+#define SSS_HASH_HMAC_KEY_IN16 (SSS_HASH_OFFSET + 0xAC)
+
+#define SSS_HASH_IV1 (SSS_HASH_OFFSET + 0xB0)
+#define SSS_HASH_IV2 (SSS_HASH_OFFSET + 0xB4)
+#define SSS_HASH_IV3 (SSS_HASH_OFFSET + 0xB8)
+#define SSS_HASH_IV4 (SSS_HASH_OFFSET + 0xBC)
+#define SSS_HASH_IV5 (SSS_HASH_OFFSET + 0xC0)
+#define SSS_HASH_IV6 (SSS_HASH_OFFSET + 0xC4)
+#define SSS_HASH_IV7 (SSS_HASH_OFFSET + 0xC8)
+#define SSS_HASH_IV8 (SSS_HASH_OFFSET + 0xCC)
+
+#define SSS_HASH_RESULT1 (SSS_HASH_OFFSET + 0x100)
+#define SSS_HASH_RESULT2 (SSS_HASH_OFFSET + 0x104)
+#define SSS_HASH_RESULT3 (SSS_HASH_OFFSET + 0x108)
+#define SSS_HASH_RESULT4 (SSS_HASH_OFFSET + 0x10C)
+#define SSS_HASH_RESULT5 (SSS_HASH_OFFSET + 0x110)
+#define SSS_HASH_RESULT6 (SSS_HASH_OFFSET + 0x114)
+#define SSS_HASH_RESULT7 (SSS_HASH_OFFSET + 0x118)
+#define SSS_HASH_RESULT8 (SSS_HASH_OFFSET + 0x11C)
+
+#define SSS_HASH_SEED1 (SSS_HASH_OFFSET + 0x140)
+#define SSS_HASH_SEED2 (SSS_HASH_OFFSET + 0x144)
+#define SSS_HASH_SEED3 (SSS_HASH_OFFSET + 0x148)
+#define SSS_HASH_SEED4 (SSS_HASH_OFFSET + 0x14C)
+#define SSS_HASH_SEED5 (SSS_HASH_OFFSET + 0x150)
+
+#define SSS_HASH_PRNG1 (SSS_HASH_OFFSET + 0x160)
+#define SSS_HASH_PRNG2 (SSS_HASH_OFFSET + 0x164)
+#define SSS_HASH_PRNG3 (SSS_HASH_OFFSET + 0x168)
+#define SSS_HASH_PRNG4 (SSS_HASH_OFFSET + 0x16C)
+#define SSS_HASH_PRNG5 (SSS_HASH_OFFSET + 0x170)
+
+/* PKA control registers */
+#define SSS_PKA_SFR0 (SSS_PKA_OFFSET + 0x00)
+#define SSS_PKA_SFR1 (SSS_PKA_OFFSET + 0x04)
+#define SSS_PKA_SFR2 (SSS_PKA_OFFSET + 0x08)
+#define SSS_PKA_SFR3 (SSS_PKA_OFFSET + 0x0C)
+#define SSS_PKA_SFR4 (SSS_PKA_OFFSET + 0x10)
+
+
+/*****************************************************************
+ OFFSET
+*****************************************************************/
+
+/* SSS_FC_INT */
+#define SSS_FC_PKDMA (1 << 0)
+#define SSS_FC_HRDMA (1 << 1)
+#define SSS_FC_BTDMA (1 << 2)
+#define SSS_FC_BRDMA (1 << 3)
+#define SSS_FC_PRNG_ERROR (1 << 4)
+#define SSS_FC_MSG_DONE (1 << 5)
+#define SSS_FC_PRNG_DONE (1 << 6)
+#define SSS_FC_PARTIAL_DONE (1 << 7)
+
+/* SSS_FC_FIFOSTAT */
+#define SSS_FC_PKFIFO_EMPTY (1 << 0)
+#define SSS_FC_PKFIFO_FULL (1 << 1)
+#define SSS_FC_HRFIFO_EMPTY (1 << 2)
+#define SSS_FC_HRFIFO_FULL (1 << 3)
+#define SSS_FC_BTFIFO_EMPTY (1 << 4)
+#define SSS_FC_BTFIFO_FULL (1 << 5)
+#define SSS_FC_BRFIFO_EMPTY (1 << 6)
+#define SSS_FC_BRFIFO_FULL (1 << 7)
+
+/* SSS_FC_FIFOCTRL */
+#define SSS_FC_SELHASH_MASK (3 << 0)
+#define SSS_FC_SELHASH_EXOUT (0 << 0)
+#define SSS_FC_SELHASH_BCIN (1 << 0)
+#define SSS_FC_SELHASH_BCOUT (2 << 0)
+#define SSS_FC_SELBC_MASK (1 << 2)
+#define SSS_FC_SELBC_AES (0 << 2)
+#define SSS_FC_SELBC_DES (1 << 2)
+
+/* SSS_FC_GLOBAL */
+#define SSS_FC_SSS_RESET (1 << 0)
+#define SSS_FC_DMA_RESET (1 << 1)
+#define SSS_FC_AES_RESET (1 << 2)
+#define SSS_FC_DES_RESET (1 << 3)
+#define SSS_FC_HASH_RESET (1 << 4)
+#define SSS_FC_AXI_ENDIAN_MASK (3 << 6)
+#define SSS_FC_AXI_ENDIAN_LE (0 << 6)
+#define SSS_FC_AXI_ENDIAN_BIBE (1 << 6)
+#define SSS_FC_AXI_ENDIAN_WIBE (2 << 6)
+
+/* Feed control - BRDMA control */
+#define SSS_FC_BRDMACFLUSH_OFF (0 << 0)
+#define SSS_FC_BRDMACFLUSH_ON (1 << 0)
+#define SSS_FC_BRDMACSWAP_ON (1 << 1)
+#define SSS_FC_BRDMACARPROT_MASK (0x7 << 2)
+#define SSS_FC_BRDMACARPROT_OFS (2)
+#define SSS_FC_BRDMACARCACHE_MASK (0xF << 5)
+#define SSS_FC_BRDMACARCACHE_OFS (5)
+
+/* Feed control - BTDMA control */
+#define SSS_FC_BTDMACFLUSH_OFF (0 << 0)
+#define SSS_FC_BTDMACFLUSH_ON (1 << 0)
+#define SSS_FC_BTDMACSWAP_ON (1 << 1)
+#define SSS_FC_BTDMACAWPROT_MASK (0x7 << 2)
+#define SSS_FC_BTDMACAWPROT_OFS (2)
+#define SSS_FC_BTDMACAWCACHE_MASK (0xF << 5)
+#define SSS_FC_BTDMACAWCACHE_OFS (5)
+
+/* Feed control - HRDMA control */
+#define SSS_FC_HRDMACFLUSH_OFF (0 << 0)
+#define SSS_FC_HRDMACFLUSH_ON (1 << 0)
+#define SSS_FC_HRDMACSWAP_ON (1 << 1)
+
+/* Feed control - PKDMA control */
+#define SSS_FC_PKDMACBYTESWAP_ON (1 << 3)
+#define SSS_FC_PKDMACDESEND_ON (1 << 2)
+#define SSS_FC_PKDMACTRANSMIT_ON (1 << 1)
+#define SSS_FC_PKDMACFLUSH_ON (1 << 0)
+
+/* Feed control - PKDMA offset */
+#define SSS_FC_SRAMOFFSET_MASK (0xFFF)
+
+/* AES control */
+#define SSS_AES_MODE_MASK (1 << 0)
+#define SSS_AES_MODE_ENC (0 << 0)
+#define SSS_AES_MODE_DEC (1 << 0)
+#define SSS_AES_OPERMODE_MASK (3 << 1)
+#define SSS_AES_OPERMODE_ECB (0 << 1)
+#define SSS_AES_OPERMODE_CBC (1 << 1)
+#define SSS_AES_OPERMODE_CTR (2 << 1)
+/*
+TODO
+CTS MODE define
+*/
+#define SSS_AES_OPERMODE_CTS (3 << 1)
+
+#define SSS_AES_FIFO_MASK (1 << 3)
+#define SSS_AES_FIFO_OFF (0 << 3)
+#define SSS_AES_FIFO_ON (1 << 3)
+#define SSS_AES_KEYSIZE_MASK (3 << 4)
+#define SSS_AES_KEYSIZE_128 (0 << 4)
+#define SSS_AES_KEYSIZE_192 (1 << 4)
+#define SSS_AES_KEYSIZE_256 (2 << 4)
+#define SSS_AES_KEYCNGMODE_MASK (1 << 6)
+#define SSS_AES_KEYCNGMODE_OFF (0 << 6)
+#define SSS_AES_KEYCNGMODE_ON (1 << 6)
+#define SSS_AES_SWAP_MASK (0x1F << 7)
+#define SSS_AES_SWAPKEY_OFF (0 << 7)
+#define SSS_AES_SWAPKEY_ON (1 << 7)
+#define SSS_AES_SWAPCNT_OFF (0 << 8)
+#define SSS_AES_SWAPCNT_ON (1 << 8)
+#define SSS_AES_SWAPIV_OFF (0 << 9)
+#define SSS_AES_SWAPIV_ON (1 << 9)
+#define SSS_AES_SWAPDO_OFF (0 << 10)
+#define SSS_AES_SWAPDO_ON (1 << 10)
+#define SSS_AES_SWAPDI_OFF (0 << 11)
+#define SSS_AES_SWAPDI_ON (1 << 11)
+#define SSS_AES_COUNTERSIZE_MASK (3 << 12)
+#define SSS_AES_COUNTERSIZE_128 (0 << 12)
+#define SSS_AES_COUNTERSIZE_64 (1 << 12)
+#define SSS_AES_COUNTERSIZE_32 (2 << 12)
+#define SSS_AES_COUNTERSIZE_16 (3 << 12)
+
+/* AES status */
+#define SSS_AES_OUTRDY_MASK (1 << 0)
+#define SSS_AES_OUTRDY_OFF (0 << 0)
+#define SSS_AES_OUTRDY_ON (1 << 0)
+#define SSS_AES_INRDY_MASK (1 << 1)
+#define SSS_AES_INRDY_OFF (0 << 1)
+#define SSS_AES_INRDY_ON (1 << 1)
+#define SSS_AES_BUSY_MASK (1 << 2)
+#define SSS_AES_BUSY_OFF (0 << 2)
+#define SSS_AES_BUSY_ON (1 << 2)
+
+/* TDES control */
+#define SSS_TDES_MODE_MASK (1 << 0)
+#define SSS_TDES_MODE_ENC (0 << 0)
+#define SSS_TDES_MODE_DEC (1 << 0)
+#define SSS_TDES_OPERMODE_MASK (1 << 1)
+#define SSS_TDES_OPERMODE_ECB (0 << 1)
+#define SSS_TDES_OPERMODE_CBC (1 << 1)
+#define SSS_TDES_SEL_MASK (3 << 3)
+#define SSS_TDES_SEL_DES (0 << 3)
+#define SSS_TDES_SEL_TDESEDE (1 << 3)
+#define SSS_TDES_SEL_TDESEEE (3 << 3)
+#define SSS_TDES_FIFO_MASK (1 << 5)
+#define SSS_TDES_FIFO_OFF (0 << 5)
+#define SSS_TDES_FIFO_ON (1 << 5)
+#define SSS_TDES_SWAP_MASK (0xF << 6)
+#define SSS_TDES_SWAPKEY_OFF (0 << 6)
+#define SSS_TDES_SWAPKEY_ON (1 << 6)
+#define SSS_TDES_SWAPIV_OFF (0 << 7)
+#define SSS_TDES_SWAPIV_ON (1 << 7)
+#define SSS_TDES_SWAPDO_OFF (0 << 8)
+#define SSS_TDES_SWAPDO_ON (1 << 8)
+#define SSS_TDES_SWAPDI_OFF (0 << 9)
+#define SSS_TDES_SWAPDI_ON (1 << 9)
+
+/* TDES status */
+#define SSS_TDES_OUTRDY_MASK (1 << 0)
+#define SSS_TDES_OUTRDY_OFF (0 << 0)
+#define SSS_TDES_OUTRDY_ON (1 << 0)
+#define SSS_TDES_INRDY_MASK (1 << 1)
+#define SSS_TDES_INRDY_OFF (0 << 1)
+#define SSS_TDES_INRDY_ON (1 << 1)
+#define SSS_TDES_BUSY_MASK (1 << 2)
+#define SSS_TDES_BUSY_OFF (0 << 2)
+#define SSS_TDES_BUSY_ON (1 << 2)
+
+/* Hash control */
+#define SSS_HASH_ENGSEL_MASK (0xF << 0)
+#define SSS_HASH_ENGSEL_SHA1HASH (0x0 << 0)
+#define SSS_HASH_ENGSEL_SHA1HMAC (0x1 << 0)
+#define SSS_HASH_ENGSEL_SHA1HMACIN (0x1 << 0)
+#define SSS_HASH_ENGSEL_SHA1HMACOUT (0x9 << 0)
+#define SSS_HASH_ENGSEL_MD5HASH (0x2 << 0)
+#define SSS_HASH_ENGSEL_MD5HMAC (0x3 << 0)
+#define SSS_HASH_ENGSEL_MD5HMACIN (0x3 << 0)
+#define SSS_HASH_ENGSEL_MD5HMACOUT (0xB << 0)
+#define SSS_HASH_ENGSEL_SHA256HASH (0x4 << 0)
+#define SSS_HASH_ENGSEL_SHA256HMAC (0x5 << 0)
+#define SSS_HASH_ENGSEL_PRNG (0x8 << 0)
+#define SSS_HASH_STARTBIT_ON (1 << 4)
+#define SSS_HASH_USERIV_EN (1 << 5)
+
+/* Hash control 2 */
+#define SSS_HASH_PAUSE_ON (1 << 0)
+
+/* Hash control - FIFO mode */
+#define SSS_HASH_FIFO_MASK (1 << 0)
+#define SSS_HASH_FIFO_OFF (0 << 0)
+#define SSS_HASH_FIFO_ON (1 << 0)
+
+/* Hash control - byte swap */
+#define SSS_HASH_SWAP_MASK (0xF << 0)
+#define SSS_HASH_SWAPKEY_OFF (0 << 0)
+#define SSS_HASH_SWAPKEY_ON (1 << 0)
+#define SSS_HASH_SWAPIV_OFF (0 << 1)
+#define SSS_HASH_SWAPIV_ON (1 << 1)
+#define SSS_HASH_SWAPDO_OFF (0 << 2)
+#define SSS_HASH_SWAPDO_ON (1 << 2)
+#define SSS_HASH_SWAPDI_OFF (0 << 3)
+#define SSS_HASH_SWAPDI_ON (1 << 3)
+
+/* Hash status */
+#define SSS_HASH_BUFRDY_MASK (1 << 0)
+#define SSS_HASH_BUFRDY_OFF (0 << 0)
+#define SSS_HASH_BUFRDY_ON (1 << 0)
+#define SSS_HASH_SEEDSETTING_MASK (1 << 1)
+#define SSS_HASH_SEEDSETTING_OFF (0 << 1)
+#define SSS_HASH_SEEDSETTING_ON (1 << 1)
+#define SSS_HASH_PRNGBUSY_MASK (1 << 2)
+#define SSS_HASH_PRNGBUSY_OFF (0 << 2)
+#define SSS_HASH_PRNGBUSY_ON (1 << 2)
+#define SSS_HASH_PARTIALDONE_MASK (1 << 4)
+#define SSS_HASH_PARTIALDONE_OFF (0 << 4)
+#define SSS_HASH_PARTIALDONE_ON (1 << 4)
+#define SSS_HASH_PRNGDONE_MASK (1 << 5)
+#define SSS_HASH_PRNGDONE_OFF (0 << 5)
+#define SSS_HASH_PRNGDONE_ON (1 << 5)
+#define SSS_HASH_MSGDONE_MASK (1 << 6)
+#define SSS_HASH_MSGDONE_OFF (0 << 6)
+#define SSS_HASH_MSGDONE_ON (1 << 6)
+#define SSS_HASH_PRNGERROR_MASK (1 << 7)
+#define SSS_HASH_PRNGERROR_OFF (0 << 7)
+#define SSS_HASH_PRNGERROR_ON (1 << 7)
+
+#endif /* __CRYPTODXE_H__ */
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.inf
new file mode 100644
index 000000000..45ae5fc0a
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/HashDxe/HashDxe.inf
@@ -0,0 +1,57 @@
+## @file
+#
+# Component description file for Crypto engine module
+#
+# This is the main routine for initializing the Crypto engine support routines.
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = HashDxe
+ FILE_GUID = 2ceb319d-ee89-4ef2-9a0d-7958abf4cd87
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = HashDxeInitialize
+
+[Sources]
+ HashDxe.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+ SamsungPlatformPkg/SamsungPlatformPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UncachedMemoryAllocationLib
+ DebugLib
+ IoLib
+ ArmGicLib
+
+[Guids]
+ gEfiHashAlgorithmSha1Guid
+ gEfiHashAlgorithmSha256Guid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid
+ gEfiHashProtocolGuid
+ gSamsungPlatformGpioProtocolGuid
+
+[Pcd]
+ gExynosPkgTokenSpaceGuid.PcdCmuBase
+ gExynosPkgTokenSpaceGuid.PcdCryptoBase
+
+[Depex]
+ TRUE
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/ComponentName.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/ComponentName.c
new file mode 100644
index 000000000..836d0b583
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/ComponentName.c
@@ -0,0 +1,231 @@
+/** @file
+ UEFI Component Name(2) protocol implementation for OHCI driver.
+
+Copyright (c) 2004 - 2007, Intel Corporation. All rights reserved.<BR>
+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 "Ohci.h"
+
+
+//
+// EFI Component Name Protocol
+//
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gOhciComponentName = {
+ OhciComponentNameGetDriverName,
+ OhciComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gOhciComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) OhciComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) OhciComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mOhciDriverNameTable[] = {
+ { "eng;en", L"Usb Ohci Driver" },
+ { NULL, NULL }
+};
+
+
+//
+// EFI Component Name Functions
+//
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mOhciDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gOhciComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ USB_HC_DEV *OhciDev;
+ EFI_USB2_HC_PROTOCOL *Usb2Hc;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure this driver is currently managing ControllerHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gOhciDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **) &Usb2Hc,
+ gOhciDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OhciDev = OHC_FROM_USB2_HC_PROTO (Usb2Hc);
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ OhciDev->CtrlNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gOhciComponentName)
+ );
+
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/ComponentName.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/ComponentName.h
new file mode 100644
index 000000000..f2f68769a
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/ComponentName.h
@@ -0,0 +1,145 @@
+/** @file
+
+ This file contains the delarations for componet name routines.
+
+Copyright (c) 2008, Intel Corporation. All rights reserved.<BR>
+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 _COMPONENT_NAME_H_
+#define _COMPONENT_NAME_H_
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciComponentNameGetControllerName (
+ 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/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/Ohci.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/Ohci.c
new file mode 100644
index 000000000..d8967a386
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/Ohci.c
@@ -0,0 +1,2345 @@
+/** @file
+
+ The OHCI driver model and HC protocol routines.
+
+Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "Ohci.h"
+#include <Protocol/Cpu.h>
+
+EFI_CPU_ARCH_PROTOCOL *gCpu;
+
+EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding = {
+ OhciDriverBindingSupported,
+ OhciDriverBindingStart,
+ OhciDriverBindingStop,
+ 0x30,
+ NULL,
+ NULL
+};
+
+/**
+ Provides software reset for the USB host controller according to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param Attributes A bit mask of the reset operation to perform. See
+ below for a list of the supported bit mask values.
+
+ @return EFI_SUCCESS The reset operation succeeded.
+ @return EFI_INVALID_PARAMETER Attributes is not valid.
+ @return EFI_UNSUPPORTED This type of reset is not currently supported.
+ @return EFI_DEVICE_ERROR Other errors.
+
+**/
+
+EFI_STATUS
+EFIAPI
+Ohci2Reset (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT16 Attributes
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+ EFI_TPL OldTpl;
+ UINT32 UsbCtr;
+
+ if ((Attributes == EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG) ||
+ (Attributes == EFI_USB_HC_RESET_HOST_WITH_DEBUG)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+
+#if 1
+ switch (Attributes) {
+ case EFI_USB_HC_RESET_GLOBAL:
+ //
+ // Stop schedule and set the Global Reset bit in the command register
+ //
+ /*
+ OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
+
+ UsbCtr = OhciReadReg(Ohc, HC_CONTROL_OFFSET);
+ UsbCtr &= (1<<9); //all except of RWC is clear
+ OhciWriteReg(Ohc, HC_CONTROL_OFFSET, UsbCtr);
+
+ gBS->Stall (OHC_ROOT_PORT_RECOVERY_STALL);*/
+ break;
+
+ case EFI_USB_HC_RESET_HOST_CONTROLLER:
+ //
+ // Stop schedule and set Host Controller Reset bit to 1
+ //
+ /*
+ OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
+
+ UsbCtr = OhciReadReg(Ohc, HC_CONTROL_OFFSET);
+ UsbCtr &= (1<<9); //all except of RWC is clear
+ OhciWriteReg(Ohc, HC_CONTROL_OFFSET, UsbCtr);*/
+ break;
+
+ default:
+ goto ON_INVAILD_PARAMETER;
+ }
+
+ OhcDumpRegs(Ohc);
+
+ //
+ // Delete all old transactions on the USB bus, then
+ // reinitialize the frame list
+ //
+ OhciFreeAllAsyncReq (Ohc);
+ OhciDestoryFrameList (Ohc);
+ OhciInitFrameList (Ohc);
+
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+
+ return EFI_SUCCESS;
+
+ON_INVAILD_PARAMETER:
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_INVALID_PARAMETER;
+#else
+ switch (Attributes) {
+ case EFI_USB_HC_RESET_GLOBAL:
+ //
+ // Stop schedule and set the Global Reset bit in the command register
+ //
+ OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
+
+ OhciSetRegBit (Ohc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);
+
+ gBS->Stall (OHC_ROOT_PORT_RESET_STALL);
+
+ //
+ // Clear the Global Reset bit to zero.
+ //
+ OhciClearRegBit (Ohc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);
+
+ gBS->Stall (OHC_ROOT_PORT_RECOVERY_STALL);
+ break;
+
+ case EFI_USB_HC_RESET_HOST_CONTROLLER:
+ //
+ // Stop schedule and set Host Controller Reset bit to 1
+ //
+ OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
+
+ OhciSetRegBit (Ohc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);
+
+ gBS->Stall (OHC_ROOT_PORT_RECOVERY_STALL);
+ break;
+
+ default:
+ goto ON_INVAILD_PARAMETER;
+ }
+
+ //
+ // Delete all old transactions on the USB bus, then
+ // reinitialize the frame list
+ //
+ OhciFreeAllAsyncReq (Ohc);
+ OhciDestoryFrameList (Ohc);
+ OhciInitFrameList (Ohc);
+
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG((EFI_D_INIT, "---Ohci2Reset()\n"));
+
+ return EFI_SUCCESS;
+
+ON_INVAILD_PARAMETER:
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_INVALID_PARAMETER;
+#endif
+}
+
+
+/**
+ Retrieves current state of the USB host controller according to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param State Variable to receive current device state.
+
+ @return EFI_SUCCESS The state is returned.
+ @return EFI_INVALID_PARAMETER State is not valid.
+ @return EFI_DEVICE_ERROR Other errors.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2GetState (
+ IN CONST EFI_USB2_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+ UINT16 UsbSts;
+ UINT16 UsbCmd;
+
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+#if 1
+ UsbSts = OhciReadReg (Ohc, HC_CONTROL_OFFSET);
+ UsbSts = (UsbSts>>6) & 0x3;
+
+ if (UsbSts == 3) {
+ *State = EfiUsbHcStateSuspend;
+
+ } else if (UsbSts == 2) {
+ *State = EfiUsbHcStateOperational;
+ } else {
+ *State = EfiUsbHcStateHalt;
+ }
+#else
+ UsbCmd = OhciReadReg (Ohc->PciIo, USBCMD_OFFSET);
+ UsbSts = OhciReadReg (Ohc->PciIo, USBSTS_OFFSET);
+
+ if ((UsbCmd & USBCMD_EGSM) !=0 ) {
+ *State = EfiUsbHcStateSuspend;
+
+ } else if ((UsbSts & USBSTS_HCH) != 0) {
+ *State = EfiUsbHcStateHalt;
+
+ } else {
+ *State = EfiUsbHcStateOperational;
+ }
+#endif
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Sets the USB host controller to a specific state according to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param State Indicates the state of the host controller that will
+ be set.
+
+ @return EFI_SUCCESS Host controller was successfully placed in the state.
+ @return EFI_INVALID_PARAMETER State is invalid.
+ @return EFI_DEVICE_ERROR Failed to set the state.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2SetState (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ EFI_USB_HC_STATE CurState;
+ USB_HC_DEV *Ohc;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ UINT16 UsbSts;
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+ Status = Ohci2GetState (This, &CurState);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (CurState == State) {
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+
+ switch (State) {
+ case EfiUsbHcStateHalt:
+ Status = OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
+ break;
+
+ case EfiUsbHcStateOperational:
+ #if 1
+ UsbSts = OhciReadReg (Ohc, HC_CONTROL_OFFSET);
+ UsbSts &= (1<<9);
+ UsbSts |= (3<<0) | (2<<6);
+ OhciWriteReg (Ohc, HC_CONTROL_OFFSET, UsbSts);
+
+ OhcDumpRegs(Ohc);
+ #else
+ UsbCmd = OhciReadReg (Ohc->PciIo, USBCMD_OFFSET);
+
+ if (CurState == EfiUsbHcStateHalt) {
+ //
+ // Set Run/Stop bit to 1, also set the bandwidht reclamation
+ // point to 64 bytes
+ //
+ UsbCmd |= USBCMD_RS | USBCMD_MAXP;
+ OhciWriteReg (Ohc->PciIo, USBCMD_OFFSET, UsbCmd);
+
+ } else if (CurState == EfiUsbHcStateSuspend) {
+ //
+ // If FGR(Force Global Resume) bit is 0, set it
+ //
+ if ((UsbCmd & USBCMD_FGR) == 0) {
+ UsbCmd |= USBCMD_FGR;
+ OhciWriteReg (Ohc->PciIo, USBCMD_OFFSET, UsbCmd);
+ }
+
+ //
+ // wait 20ms to let resume complete (20ms is specified by OHCI spec)
+ //
+ gBS->Stall (OHC_FORCE_GLOBAL_RESUME_STALL);
+
+ //
+ // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
+ //
+ UsbCmd &= ~USBCMD_FGR;
+ UsbCmd &= ~USBCMD_EGSM;
+ UsbCmd |= USBCMD_RS;
+ OhciWriteReg (Ohc->PciIo, USBCMD_OFFSET, UsbCmd);
+ }
+#endif
+ break;
+
+ case EfiUsbHcStateSuspend:
+ #if 1
+ Status = EFI_INVALID_PARAMETER;
+ #else
+ Status = Ohci2SetState (This, EfiUsbHcStateHalt);
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ //
+ // Set Enter Global Suspend Mode bit to 1.
+ //
+ UsbCmd = OhciReadReg (Ohc->PciIo, USBCMD_OFFSET);
+ UsbCmd |= USBCMD_EGSM;
+ OhciWriteReg (Ohc->PciIo, USBCMD_OFFSET, UsbCmd);
+ #endif
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return Status;
+}
+
+/**
+ Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param MaxSpeed A pointer to the max speed USB host controller
+ supports.
+ @param PortNumber A pointer to the number of root hub ports.
+ @param Is64BitCapable A pointer to an integer to show whether USB host
+ controller supports 64-bit memory addressing.
+
+ @return EFI_SUCCESS capabilities were retrieved successfully.
+ @return EFI_INVALID_PARAMETER MaxSpeed or PortNumber or Is64BitCapable is NULL.
+ @return EFI_DEVICE_ERROR An error was encountered.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2GetCapability (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ OUT UINT8 *MaxSpeed,
+ OUT UINT8 *PortNumber,
+ OUT UINT8 *Is64BitCapable
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+ UINT32 Offset;
+ UINT16 PortSC;
+ UINT32 Index;
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+
+ if ((NULL == MaxSpeed) || (NULL == PortNumber) || (NULL == Is64BitCapable)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *MaxSpeed = EFI_USB_SPEED_FULL;
+ *Is64BitCapable = (UINT8) FALSE;
+
+ *PortNumber = 3;
+/*
+ for (Index = 0; Index < USB_MAX_ROOTHUB_PORT; Index++) {
+ Offset = HC_PORT_STATUS_OFFSET + Index * 4;
+ PortSC = OhciReadReg (Ohc, Offset);
+
+ //
+ // Port status's bit 7 is reserved and always returns 1 if
+ // the port number is valid. Intel's UHCI (in EHCI controller)
+ // returns 0 in this bit if port number is invalid. Also, if
+ // PciIo IoRead returns error, 0xFFFF is returned to caller.
+ //
+ if (((PortSC & 0x80) == 0) || (PortSC == 0xFFFF)) {
+ break;
+ }
+ (*PortNumber)++;
+ }*/
+
+ Ohc->RootPorts = *PortNumber;
+
+ DEBUG ((EFI_D_INIT, "Ohci2GetCapability: %d ports\n", (UINT32)Ohc->RootPorts));
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL.
+ @param PortNumber The port to get status.
+ @param PortStatus A pointer to the current port status bits and port
+ status change bits.
+
+ @return EFI_SUCCESS status of the USB root hub port was returned in PortStatus.
+ @return EFI_INVALID_PARAMETER PortNumber is invalid.
+ @return EFI_DEVICE_ERROR Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2GetRootHubPortStatus (
+ IN CONST EFI_USB2_HC_PROTOCOL *This,
+ IN CONST UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+ UINT32 Offset;
+ UINT32 PortSC;
+
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+
+ if (PortStatus == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PortNumber >= Ohc->RootPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Offset = HC_PORT_STATUS_OFFSET + PortNumber * 4;
+ PortStatus->PortStatus = 0;
+ PortStatus->PortChangeStatus = 0;
+
+ PortSC = OhciReadReg (Ohc, Offset);
+
+ if ((PortSC & USBPORTSC_CCS) != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+
+ if ((PortSC & USBPORTSC_PED) != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
+ }
+
+ if ((PortSC & USBPORTSC_SUSP) != 0) {
+ DEBUG ((EFI_D_INIT, "Ohci2GetRootHubPortStatus: port %d is suspended\n", PortNumber));
+ PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+
+ if ((PortSC & USBPORTSC_PR) != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_RESET;
+ }
+
+ if ((PortSC & USBPORTSC_LSDA) != 0) {
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+ }
+
+ //
+ // CHC will always return one in port owner bit
+ //
+ PortStatus->PortStatus |= USB_PORT_STAT_OWNER;
+
+ if ((PortSC & USBPORTSC_CSC) != 0) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+
+ if ((PortSC & USBPORTSC_PEDC) != 0) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
+ }
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Sets a feature for the specified root hub port according to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL.
+ @param PortNumber Specifies the root hub port whose feature is
+ requested to be set.
+ @param PortFeature Indicates the feature selector associated with the
+ feature set request.
+
+ @return EFI_SUCCESS PortFeature was set for the root port.
+ @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+ @return EFI_DEVICE_ERROR Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2SetRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+ EFI_TPL OldTpl;
+ UINT32 Offset;
+ UINT32 PortSC;
+ UINT32 Command;
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+
+ if (PortNumber >= Ohc->RootPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Offset = HC_PORT_STATUS_OFFSET + PortNumber * 4;
+
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+ PortSC = OhciReadReg (Ohc, Offset);
+
+ switch (PortFeature) {
+ case EfiUsbPortSuspend:
+ /*
+ Command = OhciReadReg (Ohc, USBCMD_OFFSET);
+ if ((Command & USBCMD_EGSM) == 0) {
+ //
+ // if global suspend is not active, can set port suspend
+ //
+ PortSC &= 0xfff5;
+ PortSC |= USBPORTSC_SUSP;
+ }*/
+ break;
+
+ case EfiUsbPortReset:
+ //PortSC &= ~0xFFFF0000;
+ PortSC = USBPORTSC_PR;
+ break;
+
+ case EfiUsbPortPower:
+ //PortSC &= ~0xFFFF0000;
+ PortSC = USBPORTSC_PPS;
+ break;
+
+ case EfiUsbPortEnable:
+ //PortSC &= ~0xFFFF0000;
+ PortSC = USBPORTSC_PED;
+ break;
+
+ default:
+ gBS->RestoreTPL (OldTpl);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OhciWriteReg (Ohc, Offset, PortSC);
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Clears a feature for the specified root hub port according to Uefi 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param PortNumber Specifies the root hub port whose feature is
+ requested to be cleared.
+ @param PortFeature Indicates the feature selector associated with the
+ feature clear request.
+
+ @return EFI_SUCCESS PortFeature was cleared for the USB root hub port.
+ @return EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
+ @return EFI_DEVICE_ERROR Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2ClearRootHubPortFeature (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+ EFI_TPL OldTpl;
+ UINT32 Offset;
+ UINT32 PortSC;
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+
+ if (PortNumber >= Ohc->RootPorts) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Offset = HC_PORT_STATUS_OFFSET + PortNumber * 4;
+
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+ PortSC = OhciReadReg (Ohc, Offset);
+
+ switch (PortFeature) {
+ case EfiUsbPortEnable:
+ //PortSC &= ~0xFFFF0000;
+ PortSC = USBPORTSC_CCS;
+ break;
+
+ case EfiUsbPortSuspend:
+ PortSC = 0;
+ /*
+ //
+ // Cause a resume on the specified port if in suspend mode.
+ //
+ PortSC &= ~USBPORTSC_SUSP;*/
+ break;
+
+ case EfiUsbPortPower:
+ PortSC = 0;
+ //PortSC &= ~0xFFFF0000;
+ //
+ // No action
+ //
+ break;
+
+ case EfiUsbPortReset:
+ /*PortSC &= ~0xFFFF0000;
+ //iky temporary
+ PortSC |= USBPORTSC_PRSC;
+ OhciWriteReg (Ohc, Offset, PortSC);
+ while(OhciReadReg(Ohc, Offset) & USBPORTSC_PRSC);
+
+ PortSC = OhciReadReg (Ohc, Offset);
+ PortSC |= USBPORTSC_CSC;
+ PortSC &= ~0xFFFF0000;
+ OhciWriteReg (Ohc, Offset, PortSC);
+
+ PortSC = OhciReadReg (Ohc, Offset);
+ PortSC &= ~0xFFFF0000;
+ PortSC |= USBPORTSC_PED;
+ //PortSC &= ~USBPORTSC_PR;*/
+ break;
+
+ case EfiUsbPortConnectChange:
+ //PortSC &= ~0xFFFF0000;
+ //PortSC |= USBPORTSC_CSC;
+ PortSC = USBPORTSC_CSC;
+ break;
+
+ case EfiUsbPortEnableChange:
+ //PortSC &= ~0xFFFF0000;
+ //PortSC |= USBPORTSC_PEDC;
+ PortSC = USBPORTSC_PEDC;
+ break;
+
+ case EfiUsbPortSuspendChange:
+ //
+ // Root hub does not support this
+ //
+ //PortSC &= ~0xFFFF0000;
+ break;
+
+ case EfiUsbPortOverCurrentChange:
+ //
+ // Root hub does not support this
+ //
+ //PortSC &= ~0xFFFF0000;
+ break;
+
+ case EfiUsbPortResetChange:
+ //
+ // Root hub does not support this
+ //
+ //PortSC &= ~0xFFFF0000;
+ break;
+
+ default:
+ gBS->RestoreTPL (OldTpl);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OhciWriteReg (Ohc, Offset, PortSC);
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Submits control transfer to a target USB device accroding to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param DeviceSpeed Device speed.
+ @param MaximumPacketLength Maximum packet size of the target endpoint.
+ @param Request USB device request to send.
+ @param TransferDirection Data direction of the Data stage in control transfer.
+ @param Data Data to transmit/receive in data stage.
+ @param DataLength Length of the data.
+ @param TimeOut Maximum time, in microseconds, for transfer to complete.
+ @param Translator Transaction translator to be used by this device.
+ @param TransferResult Variable to receive the transfer result.
+
+ @return EFI_SUCCESS The control transfer was completed successfully.
+ @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
+ @return EFI_INVALID_PARAMETER Some parameters are invalid.
+ @return EFI_TIMEOUT Failed due to timeout.
+ @return EFI_DEVICE_ERROR Failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2ControlTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+ OHCI_ED_HW *Ed;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ OHCI_QH_RESULT QhResult;
+ UINT8 PktId;
+ UINT8 *RequestPhy;
+ VOID *RequestMap;
+ UINT8 *DataPhy;
+ VOID *DataMap;
+ BOOLEAN IsSlowDevice;
+ UINTN TransferDataLength;
+
+ DEBUG((EFI_D_INIT, "+++Ohci2ControlTransfer(DeviceAddr : %d, Data : 0x%p, Datas : %d, Max : %d, Dir : %d)\n", DeviceAddress, Data, *DataLength, MaximumPacketLength, TransferDirection));
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+ Ed = NULL;
+ DataPhy = NULL;
+ DataMap = NULL;
+ RequestPhy = NULL;
+ RequestMap = NULL;
+
+ IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
+
+ //
+ // Parameters Checking
+ //
+ if (Request == NULL || TransferResult == NULL) {
+ DEBUG((EFI_D_ERROR, "FAIL! NULL point\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //iky ???
+
+ if (IsSlowDevice && (MaximumPacketLength != 8)) {
+ DEBUG((EFI_D_ERROR, "FAIL! not matched MaximumPacketLength1\n"));
+ //MaximumPacketLength = 8;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
+ (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
+ DEBUG((EFI_D_ERROR, "FAIL! not matched MaximumPacketLength2\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((TransferDirection != EfiUsbNoData) && (Data == NULL || DataLength == NULL)) {
+ DEBUG((EFI_D_ERROR, "FAIL! no DATA\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TransferDirection == EfiUsbNoData) {
+ TransferDataLength = 0;
+ } else {
+ TransferDataLength = *DataLength;
+ }
+
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+
+ //
+ // If errors exist that cause host controller halt,
+ // clear status then return EFI_DEVICE_ERROR.
+ //
+ OhciAckAllInterrupt (Ohc);
+
+ if (!OhciIsHcWorking (Ohc)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+
+ //
+ // Map the Request and data for bus master access,
+ // then create a list of TD for this transfer
+ //
+ Status = OhciMapUserRequest (Ohc, Request, &RequestPhy, &RequestMap);
+
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ Status = OhciMapUserData (Ohc, TransferDirection, Data, DataLength, &PktId, &DataPhy, &DataMap);
+
+ if (EFI_ERROR (Status)) {
+ Ohc->PciIo->Unmap (Ohc->PciIo, RequestMap);
+ goto ON_EXIT;
+ }
+
+ Ed = OhciCreateCtrlTds (
+ Ohc,
+ DeviceAddress,
+ PktId,
+ (UINT8*)Request,
+ RequestPhy,
+ (UINT8*)Data,
+ DataPhy,
+ TransferDataLength,
+ (UINT8) MaximumPacketLength,
+ IsSlowDevice
+ );
+
+ if (Ed == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UNMAP_DATA;
+ }
+
+ gCpu->FlushDataCache (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)Ed, sizeof(OHCI_ED_HW), EfiCpuFlushTypeWriteBackInvalidate);
+ {
+ OHCI_TD_HW *Td = Ed->head_td_ptr;
+ OHCI_TD_SW *Before = NULL;
+ OHCI_TD_SW *Current = NULL;
+
+ Ohc->CtrlQh = UsbHcAllocateMem (Ohc->MemPool, sizeof(OHCI_TD_SW));
+ Ohc->CtrlQh->TdHw = NULL;
+ Ohc->CtrlQh->NextTd = NULL;
+
+ Before = Ohc->CtrlQh;
+ do
+ {
+ Current = UsbHcAllocateMem (Ohc->MemPool, sizeof(OHCI_TD_SW));
+ Current->TdHw = NULL;
+ Current->NextTd = NULL;
+ Before->NextTd = Current;
+ Before->TdHw = Td;
+ Before->DataLen = (Td->buffer_end - Td->current_buf_ptr + 1);
+ Before = Current;
+
+ gCpu->FlushDataCache (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)Td, sizeof(OHCI_TD_HW), EfiCpuFlushTypeWriteBackInvalidate);
+ } while(Td = Td->next_td);
+ }
+
+ OhciDumpEd(Ed);
+
+#if 1
+ //
+ // According to the speed of the end point, link
+ // the TD to corrosponding queue head, then check
+ // the execution result
+ //
+ OhciLinkTdToQh (Ohc, Ed, 0);
+ Status = OhciExecuteTransfer (Ohc, Ed, TimeOut, IsSlowDevice, &QhResult);
+ OhciUnlinkTdFromQh (Ohc->CtrlQh, NULL);
+
+ Ohc->PciIo->Flush (Ohc);
+
+ *TransferResult = QhResult.Result;
+
+ if (DataLength != NULL) {
+ *DataLength = QhResult.Complete;
+ }
+
+ OhciDestoryTds (Ohc, Ohc->CtrlQh);
+
+UNMAP_DATA:
+ if(DataMap)
+ {
+ DEBUG((EFI_D_INIT, "Unmap(DataMap)\n"));
+ Ohc->PciIo->Unmap (Ohc->PciIo, DataMap);
+ }
+ if(RequestMap)
+ {
+ DEBUG((EFI_D_INIT, "Unmap(RequestMap)\n"));
+ Ohc->PciIo->Unmap (Ohc->PciIo, RequestMap);
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+
+ return Status;
+#else
+ //
+ // According to the speed of the end point, link
+ // the TD to corrosponding queue head, then check
+ // the execution result
+ //
+ OhciLinkTdToQh (Ohc, Ed);
+ Status = OhciExecuteTransfer (Ohc, Ed, TimeOut, IsSlowDevice, &QhResult);
+ OhciUnlinkTdFromQh (Ohc->CtrlQh, TDs);
+
+ Ohc->PciIo->Flush (Ohc->PciIo);
+
+ *TransferResult = QhResult.Result;
+
+ if (DataLength != NULL) {
+ *DataLength = QhResult.Complete;
+ }
+
+ OhciDestoryTds (Ohc, TDs);
+
+UNMAP_DATA:
+ Ohc->PciIo->Unmap (Ohc->PciIo, DataMap);
+ Ohc->PciIo->Unmap (Ohc->PciIo, RequestMap);
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+
+ return Status;
+#endif
+}
+
+
+/**
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and direction.
+ @param DeviceSpeed Device speed.
+ @param MaximumPacketLength Maximum packet size of the target endpoint.
+ @param DataBuffersNumber Number of data buffers prepared for the transfer.
+ @param Data Array of pointers to the buffers of data.
+ @param DataLength On input, size of the data buffer, On output,
+ actually transferred data size.
+ @param DataToggle On input, data toggle to use; On output, next data toggle.
+ @param TimeOut Maximum time out, in microseconds.
+ @param Translator A pointr to the transaction translator data.
+ @param TransferResult Variable to receive transfer result.
+
+ @return EFI_SUCCESS The bulk transfer was completed successfully.
+ @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
+ @return EFI_INVALID_PARAMETER Some parameters are invalid.
+ @return EFI_TIMEOUT Failed due to timeout.
+ @return EFI_DEVICE_ERROR Failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2BulkTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ EFI_USB_DATA_DIRECTION Direction;
+ EFI_TPL OldTpl;
+ USB_HC_DEV *Ohc;
+ OHCI_TD_HW *TDs;
+ OHCI_QH_SW *BulkQh;
+ OHCI_QH_RESULT QhResult;
+ EFI_STATUS Status;
+ UINT8 PktId;
+ UINT8 *DataPhy;
+ VOID *DataMap;
+#if 1
+ DEBUG((EFI_D_INIT, "+++Ohci2BulkTransfer()\n"));
+ DEBUG((EFI_D_INIT, "---Ohci2BulkTransfer()\n"));
+#else
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+ DataPhy = NULL;
+ DataMap = NULL;
+
+ if (DeviceSpeed == EFI_USB_SPEED_LOW) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DataLength == NULL) || (*DataLength == 0) || (Data == NULL) || (TransferResult == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&
+ (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_OUT_OF_RESOURCES;
+
+ //
+ // If has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ OhciAckAllInterrupt (Ohc);
+
+ if (!OhciIsHcWorking (Ohc->PciIo)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+
+ //
+ // Map the source data buffer for bus master access,
+ // then create a list of TDs
+ //
+ if ((EndPointAddress & 0x80) != 0) {
+ Direction = EfiUsbDataIn;
+ } else {
+ Direction = EfiUsbDataOut;
+ }
+
+ Status = OhciMapUserData (Ohc, Direction, *Data, DataLength, &PktId, &DataPhy, &DataMap);
+
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ Status = EFI_OUT_OF_RESOURCES;
+ TDs = OhciCreateBulkOrIntTds (
+ Ohc,
+ DeviceAddress,
+ EndPointAddress,
+ PktId,
+ (UINT8 *)*Data,
+ DataPhy,
+ *DataLength,
+ DataToggle,
+ (UINT8) MaximumPacketLength,
+ FALSE
+ );
+
+ if (TDs == NULL) {
+ Ohc->PciIo->Unmap (Ohc->PciIo, DataMap);
+ goto ON_EXIT;
+ }
+
+
+ //
+ // Link the TDs to bulk queue head. According to the platfore
+ // defintion of OHCI_NO_BW_RECLAMATION, BulkQh is either configured
+ // to do full speed bandwidth reclamation or not.
+ //
+ BulkQh = Ohc->BulkQh;
+
+ OhciLinkTdToQh (Ohc, BulkQh, TDs);
+ Status = OhciExecuteTransfer (Ohc, BulkQh, TDs, TimeOut, FALSE, &QhResult);
+ OhciUnlinkTdFromQh (BulkQh, TDs);
+
+ Ohc->PciIo->Flush (Ohc->PciIo);
+
+ *TransferResult = QhResult.Result;
+ *DataToggle = QhResult.NextToggle;
+ *DataLength = QhResult.Complete;
+
+ OhciDestoryTds (Ohc, TDs);
+ Ohc->PciIo->Unmap (Ohc->PciIo, DataMap);
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+#endif
+ return Status;
+}
+
+/**
+ Submits an asynchronous interrupt transfer to an
+ interrupt endpoint of a USB device according to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and direction.
+ @param DeviceSpeed Device speed.
+ @param MaximumPacketLength Maximum packet size of the target endpoint.
+ @param IsNewTransfer If TRUE, submit a new transfer, if FALSE cancel old transfer.
+ @param DataToggle On input, data toggle to use; On output, next data toggle.
+ @param PollingInterval Interrupt poll rate in milliseconds.
+ @param DataLength On input, size of the data buffer, On output,
+ actually transferred data size.
+ @param Translator A pointr to the transaction translator data.
+ @param CallBackFunction Function to call periodically.
+ @param Context User context.
+
+ @return EFI_SUCCESS Transfer was submitted.
+ @return EFI_INVALID_PARAMETER Some parameters are invalid.
+ @return EFI_OUT_OF_RESOURCES Failed due to a lack of resources.
+ @return EFI_DEVICE_ERROR Can't read register.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2AsyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval,
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
+ IN VOID *Context
+ )
+{
+#if 1
+ USB_HC_DEV *Ohc;
+ OHCI_ED_HW *Ed;
+ BOOLEAN IsSlowDevice;
+ OHCI_TD_HW *IntTds;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ UINT8 *DataPtr;
+ UINT8 *DataPhy;
+ UINT8 PktId;
+ OHCI_QH_RESULT QhResult;
+
+ DEBUG((EFI_D_INIT, "+++Ohci2AsyncInterruptTransfer(EP%d)\n", EndPointAddress));
+
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+ IntTds = NULL;
+ DataPtr = NULL;
+ DataPhy = NULL;
+
+ IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
+
+ if ((EndPointAddress & 0x80) == 0) {
+ DEBUG((EFI_D_ERROR, "FAIL! EndPointAddress ERROR\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Delete Async interrupt transfer request
+ //
+ if (!IsNewTransfer) {
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+ Status = OhciRemoveAsyncReq (Ohc, DeviceAddress, EndPointAddress, DataToggle);
+
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+
+ if (PollingInterval < 1 || PollingInterval > 255) {
+ DEBUG((EFI_D_ERROR, "FAIL! PollingInterval ERROR\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DataLength == 0) {
+ DEBUG((EFI_D_ERROR, "FAIL! DataLength ERROR\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {
+ DEBUG((EFI_D_ERROR, "FAIL! DataToggle ERROR\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ OhciAckAllInterrupt (Ohc);
+
+ if (!OhciIsHcWorking (Ohc->PciIo)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((EndPointAddress & 0x80) == 0) {
+ PktId = OUTPUT_PACKET_ID;
+ } else {
+ PktId = INPUT_PACKET_ID;
+ }
+
+ //
+ // Allocate and map source data buffer for bus master access.
+ //
+ DataPtr = UsbHcAllocateMem (Ohc->MemPool, DataLength);
+
+ if (DataPtr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DataPhy = (UINT8 *) (UINTN) UsbHcGetPciAddressForHostMem (Ohc->MemPool, DataPtr, DataLength);
+
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+
+ /*Qh = OhciCreateQh (Ohc, PollingInterval);
+
+ if (Qh == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_DATA;
+ }*/
+
+ Ed = OhciCreateBulkOrIntTds (
+ Ohc,
+ DeviceAddress,
+ EndPointAddress,
+ PktId,
+ DataPtr,
+ DataPhy,
+ DataLength,
+ DataToggle,
+ (UINT8) MaximumPacketLength,
+ IsSlowDevice
+ );
+
+ if (Ed == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG((EFI_D_ERROR, "FAIL! OhciCreateBulkOrIntTds ERROR\n"));
+ goto DESTORY_QH;
+ }
+
+ gCpu->FlushDataCache (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)Ed, sizeof(OHCI_ED_HW), EfiCpuFlushTypeWriteBackInvalidate);
+ {
+ OHCI_TD_HW *Td = Ed->head_td_ptr;
+ OHCI_TD_SW *Before = NULL;
+ OHCI_TD_SW *Current = NULL;
+
+ Ohc->IntrQh = UsbHcAllocateMem (Ohc->MemPool, sizeof(OHCI_TD_SW));
+ Ohc->IntrQh->TdHw = NULL;
+ Ohc->IntrQh->NextTd = NULL;
+
+ Before = Ohc->IntrQh;
+ do
+ {
+ Current = UsbHcAllocateMem (Ohc->MemPool, sizeof(OHCI_TD_SW));
+ Current->TdHw = NULL;
+ Current->NextTd = NULL;
+ Before->NextTd = Current;
+ Before->TdHw = Td;
+ Before->TdHw->gtd_info.b.buffer_rounding = 0;
+ Before->Data = Td->current_buf_ptr;
+ Before->DataLen = (Td->buffer_end - Td->current_buf_ptr + 1);
+ Before = Current;
+
+ gCpu->FlushDataCache (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)Td, sizeof(OHCI_TD_HW), EfiCpuFlushTypeWriteBackInvalidate);
+ } while(Td = Td->next_td);
+ }
+
+ OhciDumpEd(Ed);
+
+ OhciLinkTdToQh (Ohc, Ed, 1);
+
+ //
+ // Save QH-TD structures to async Interrupt transfer list,
+ // for monitor interrupt transfer execution routine use.
+ //
+ Status = OhciCreateAsyncReq (
+ Ohc,
+ Ed,
+ Ohc->IntrQh,
+ DeviceAddress,
+ EndPointAddress,
+ DataLength,
+ PollingInterval,
+ DataPtr,
+ CallBackFunction,
+ Context,
+ IsSlowDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto DESTORY_QH;
+ }
+
+ //OhciLinkQhToFrameList (Ohc, Qh);
+
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG((EFI_D_INIT, "---Ohci2AsyncInterruptTransfer()\n"));
+
+ return EFI_SUCCESS;
+
+DESTORY_QH:
+ //UsbHcFreeMem (Ohc->MemPool, Qh, sizeof (OHCI_QH_SW));
+
+FREE_DATA:
+ UsbHcFreeMem (Ohc->MemPool, DataPtr, DataLength);
+ Ohc->PciIo->Flush (Ohc->PciIo);
+
+ gBS->RestoreTPL (OldTpl);
+
+#else
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+ Qh = NULL;
+ IntTds = NULL;
+ DataPtr = NULL;
+ DataPhy = NULL;
+
+ IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
+
+ if ((EndPointAddress & 0x80) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Delete Async interrupt transfer request
+ //
+ if (!IsNewTransfer) {
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+ Status = OhciRemoveAsyncReq (Ohc, DeviceAddress, EndPointAddress, DataToggle);
+
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+
+ if (PollingInterval < 1 || PollingInterval > 255) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DataLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ OhciAckAllInterrupt (Ohc);
+
+ if (!OhciIsHcWorking (Ohc->PciIo)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((EndPointAddress & 0x80) == 0) {
+ PktId = OUTPUT_PACKET_ID;
+ } else {
+ PktId = INPUT_PACKET_ID;
+ }
+
+ //
+ // Allocate and map source data buffer for bus master access.
+ //
+ DataPtr = UsbHcAllocateMem (Ohc->MemPool, DataLength);
+
+ if (DataPtr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DataPhy = (UINT8 *) (UINTN) UsbHcGetPciAddressForHostMem (Ohc->MemPool, DataPtr, DataLength);
+
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+
+ Qh = OhciCreateQh (Ohc, PollingInterval);
+
+ if (Qh == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_DATA;
+ }
+
+ IntTds = OhciCreateBulkOrIntTds (
+ Ohc,
+ DeviceAddress,
+ EndPointAddress,
+ PktId,
+ DataPtr,
+ DataPhy,
+ DataLength,
+ DataToggle,
+ (UINT8) MaximumPacketLength,
+ IsSlowDevice
+ );
+
+ if (IntTds == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto DESTORY_QH;
+ }
+
+ OhciLinkTdToQh (Ohc, Qh, IntTds);
+
+ //
+ // Save QH-TD structures to async Interrupt transfer list,
+ // for monitor interrupt transfer execution routine use.
+ //
+ Status = OhciCreateAsyncReq (
+ Ohc,
+ Qh,
+ IntTds,
+ DeviceAddress,
+ EndPointAddress,
+ DataLength,
+ PollingInterval,
+ DataPtr,
+ CallBackFunction,
+ Context,
+ IsSlowDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto DESTORY_QH;
+ }
+
+ OhciLinkQhToFrameList (Ohc, Qh);
+
+ gBS->RestoreTPL (OldTpl);
+
+ DEBUG((EFI_D_INIT, "---Ohci2AsyncInterruptTransfer()\n"));
+
+ return EFI_SUCCESS;
+
+DESTORY_QH:
+ UsbHcFreeMem (Ohc->MemPool, Qh, sizeof (OHCI_QH_SW));
+
+FREE_DATA:
+ UsbHcFreeMem (Ohc->MemPool, DataPtr, DataLength);
+ Ohc->PciIo->Flush (Ohc->PciIo);
+
+ gBS->RestoreTPL (OldTpl);
+#endif
+}
+
+/**
+ Submits synchronous interrupt transfer to an interrupt endpoint
+ of a USB device according to UEFI 2.0 spec.
+
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and direction.
+ @param DeviceSpeed Device speed.
+ @param MaximumPacketLength Maximum packet size of the target endpoint.
+ @param Data Array of pointers to the buffers of data.
+ @param DataLength On input, size of the data buffer, On output,
+ actually transferred data size.
+ @param DataToggle On input, data toggle to use; On output, next data toggle.
+ @param TimeOut Maximum time out, in microseconds.
+ @param Translator A pointr to the transaction translator data.
+ @param TransferResult Variable to receive transfer result.
+
+ @return EFI_SUCCESS The transfer was completed successfully.
+ @return EFI_OUT_OF_RESOURCES Failed due to lack of resource.
+ @return EFI_INVALID_PARAMETER Some parameters are invalid.
+ @return EFI_TIMEOUT Failed due to timeout.
+ @return EFI_DEVICE_ERROR Failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2SyncInterruptTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+{
+ EFI_STATUS Status;
+ USB_HC_DEV *Ohc;
+ OHCI_TD_HW *TDs;
+ OHCI_QH_RESULT QhResult;
+ EFI_TPL OldTpl;
+ UINT8 *DataPhy;
+ VOID *DataMap;
+ UINT8 PktId;
+ BOOLEAN IsSlowDevice;
+#if 1
+ DEBUG((EFI_D_INIT, "+++Ohci2SyncInterruptTransfer()\n"));
+ DEBUG((EFI_D_INIT, "---Ohci2SyncInterruptTransfer()\n"));
+#else
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+ DataPhy = NULL;
+ DataMap = NULL;
+ TDs = NULL;
+
+ if (DeviceSpeed == EFI_USB_SPEED_HIGH) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
+
+ if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((EndPointAddress & 0x80) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataLength == 0) || (MaximumPacketLength > 64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsSlowDevice && (MaximumPacketLength > 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ Status = EFI_DEVICE_ERROR;
+
+
+ OhciAckAllInterrupt (Ohc);
+
+ if (!OhciIsHcWorking (Ohc->PciIo)) {
+ return Status;
+ }
+
+ OldTpl = gBS->RaiseTPL (OHCI_TPL);
+
+ //
+ // Map the source data buffer for bus master access.
+ // Create Tds list, then link it to the OHC's interrupt list
+ //
+ Status = OhciMapUserData (
+ Ohc,
+ EfiUsbDataIn,
+ Data,
+ DataLength,
+ &PktId,
+ &DataPhy,
+ &DataMap
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ TDs = OhciCreateBulkOrIntTds (
+ Ohc,
+ DeviceAddress,
+ EndPointAddress,
+ PktId,
+ (UINT8 *)Data,
+ DataPhy,
+ *DataLength,
+ DataToggle,
+ (UINT8) MaximumPacketLength,
+ IsSlowDevice
+ );
+
+ if (TDs == NULL) {
+ Ohc->PciIo->Unmap (Ohc->PciIo, DataMap);
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+
+ OhciLinkTdToQh (Ohc, Ohc->SyncIntQh, TDs);
+
+ Status = OhciExecuteTransfer (Ohc, Ohc->SyncIntQh, TDs, TimeOut, IsSlowDevice, &QhResult);
+
+ OhciUnlinkTdFromQh (Ohc->SyncIntQh, TDs);
+ Ohc->PciIo->Flush (Ohc->PciIo);
+
+ *TransferResult = QhResult.Result;
+ *DataToggle = QhResult.NextToggle;
+ *DataLength = QhResult.Complete;
+
+ OhciDestoryTds (Ohc, TDs);
+ Ohc->PciIo->Unmap (Ohc->PciIo, DataMap);
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+#endif
+ return Status;
+}
+
+
+/**
+ Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and direction.
+ @param DeviceSpeed Device speed.
+ @param MaximumPacketLength Maximum packet size of the target endpoint.
+ @param DataBuffersNumber Number of data buffers prepared for the transfer.
+ @param Data Array of pointers to the buffers of data.
+ @param DataLength On input, size of the data buffer, On output,
+ actually transferred data size.
+ @param Translator A pointr to the transaction translator data.
+ @param TransferResult Variable to receive transfer result.
+
+ @return EFI_UNSUPPORTED
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2IsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ OUT UINT32 *TransferResult
+ )
+{
+ DEBUG((EFI_D_INIT, "+++Ohci2IsochronousTransfer()\n"));
+ DEBUG((EFI_D_INIT, "---Ohci2IsochronousTransfer()\n"));
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
+
+ @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.
+ @param DeviceAddress Target device address.
+ @param EndPointAddress Endpoint number and direction.
+ @param DeviceSpeed Device speed.
+ @param MaximumPacketLength Maximum packet size of the target endpoint.
+ @param DataBuffersNumber Number of data buffers prepared for the transfer.
+ @param Data Array of pointers to the buffers of data.
+ @param DataLength On input, size of the data buffer, On output,
+ actually transferred data size.
+ @param Translator A pointr to the transaction translator data.
+ @param IsochronousCallBack Function to call when the transfer complete.
+ @param Context Pass to the call back function as parameter.
+
+ @return EFI_UNSUPPORTED
+
+**/
+EFI_STATUS
+EFIAPI
+Ohci2AsyncIsochronousTransfer (
+ IN EFI_USB2_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DeviceSpeed,
+ IN UINTN MaximumPacketLength,
+ IN UINT8 DataBuffersNumber,
+ IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
+ IN UINTN DataLength,
+ IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context
+ )
+{
+ DEBUG((EFI_D_INIT, "+++Ohci2AsyncIsochronousTransfer()\n"));
+ DEBUG((EFI_D_INIT, "---Ohci2AsyncIsochronousTransfer()\n"));
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Entry point for EFI drivers.
+
+ @param ImageHandle EFI_HANDLE.
+ @param SystemTable EFI_SYSTEM_TABLE.
+
+ @retval EFI_SUCCESS Driver is successfully loaded.
+ @return Others Failed.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS status;
+ DEBUG((EFI_D_INIT, "+++OhciDriverEntryPoint()\n"));
+
+ status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gOhciDriverBinding,
+ ImageHandle,
+ &gOhciComponentName,
+ &gOhciComponentName2
+ );
+
+ DEBUG((EFI_D_INIT, "---OhciDriverEntryPoint(%r)\n", status));
+
+ return status;
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has UsbHcProtocol installed will be supported.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ EFI_STATUS OpenStatus;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB_CLASSC UsbClassCReg;
+
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (OpenStatus)) {
+ DEBUG((EFI_D_ERROR, "--%a(OpenProtocol Error):%d\n", __FUNCTION__, __LINE__));
+ return OpenStatus;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (USB_CLASSC) / sizeof (UINT8),
+ &UsbClassCReg
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "--%a(Pci.Read Error):%d\n", __FUNCTION__, __LINE__));
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Test whether the controller belongs to OHCI type
+ //
+ if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
+ (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
+ (UsbClassCReg.ProgInterface != PCI_IF_OHCI)
+ ) {
+ DEBUG ((EFI_D_ERROR, "FAIL! INTERFACE IS NOT OHCI(%X, %X, %X, %X, %X, %X)\n",
+ UsbClassCReg.BaseCode,
+ PCI_CLASS_SERIAL,
+ UsbClassCReg.SubClassCode,
+ PCI_CLASS_SERIAL_USB,
+ UsbClassCReg.ProgInterface,
+ PCI_IF_OHCI
+ ));
+ Status = EFI_UNSUPPORTED;
+ }
+
+ON_EXIT:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ DEBUG((EFI_D_INIT, "OhciDriverBindingSupported(%r)\n", Status));
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+
+ return Status;
+
+}
+
+
+/**
+ Allocate and initialize the empty OHCI device.
+
+ @param PciIo The PCIIO to use.
+ @param OriginalPciAttributes The original PCI attributes.
+
+ @return Allocated OHCI device. If err, return NULL.
+
+**/
+USB_HC_DEV *
+OhciAllocateDev (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT64 OriginalPciAttributes
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+ EFI_STATUS Status;
+ UINT32 i;
+
+ Ohc = AllocateZeroPool (sizeof (USB_HC_DEV));
+
+ if (Ohc == NULL) {
+ return NULL;
+ }
+
+ //
+ // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.
+ // USB_HC_PROTOCOL is for EFI 1.1 backward compability.
+ //
+ Ohc->Signature = USB_HC_DEV_SIGNATURE;
+ Ohc->Usb2Hc.GetCapability = Ohci2GetCapability;
+ Ohc->Usb2Hc.Reset = Ohci2Reset;
+ Ohc->Usb2Hc.GetState = Ohci2GetState;
+ Ohc->Usb2Hc.SetState = Ohci2SetState;
+ Ohc->Usb2Hc.ControlTransfer = Ohci2ControlTransfer;
+ Ohc->Usb2Hc.BulkTransfer = Ohci2BulkTransfer;
+ Ohc->Usb2Hc.AsyncInterruptTransfer = Ohci2AsyncInterruptTransfer;
+ Ohc->Usb2Hc.SyncInterruptTransfer = Ohci2SyncInterruptTransfer;
+ Ohc->Usb2Hc.IsochronousTransfer = Ohci2IsochronousTransfer;
+ Ohc->Usb2Hc.AsyncIsochronousTransfer = Ohci2AsyncIsochronousTransfer;
+ Ohc->Usb2Hc.GetRootHubPortStatus = Ohci2GetRootHubPortStatus;
+ Ohc->Usb2Hc.SetRootHubPortFeature = Ohci2SetRootHubPortFeature;
+ Ohc->Usb2Hc.ClearRootHubPortFeature = Ohci2ClearRootHubPortFeature;
+ Ohc->Usb2Hc.MajorRevision = 0x1;
+ Ohc->Usb2Hc.MinorRevision = 0x1;
+
+ Ohc->Destory = NULL;
+ Ohc->PciIo = PciIo;
+ Ohc->OriginalPciAttributes = OriginalPciAttributes;
+ Ohc->MemPool = UsbHcInitMemPool (PciIo, TRUE, 0);
+
+ if (Ohc->MemPool == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ InitializeListHead (&Ohc->AsyncIntList);
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ OhciMonitorAsyncReqList,
+ Ohc,
+ &Ohc->AsyncIntMonitor
+ );
+
+ if (EFI_ERROR (Status)) {
+ UsbHcFreeMemPool (Ohc->MemPool);
+ goto ON_ERROR;
+ }
+
+ for(i=0; i<15; ++i)
+ {
+ Ohc->EdHw[i] = OhciCreateEd(Ohc, 0, 0, 0, 0);
+ }
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+
+ return Ohc;
+
+ON_ERROR:
+ FreePool (Ohc);
+ return NULL;
+}
+
+
+/**
+ Free the OHCI device and release its associated resources.
+
+ @param Ohc The OHCI device to release.
+
+**/
+VOID
+OhciFreeDev (
+ IN USB_HC_DEV *Ohc
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+
+ if (Ohc->AsyncIntMonitor != NULL) {
+ gBS->CloseEvent (Ohc->AsyncIntMonitor);
+ }
+
+ if (Ohc->ExitBootServiceEvent != NULL) {
+ gBS->CloseEvent (Ohc->ExitBootServiceEvent);
+ }
+
+ if (Ohc->MemPool != NULL) {
+ UsbHcFreeMemPool (Ohc->MemPool);
+ }
+
+ if (Ohc->CtrlNameTable != NULL) {
+ FreeUnicodeStringTable (Ohc->CtrlNameTable);
+ }
+
+ FreePool (Ohc);
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+}
+
+
+/**
+ Uninstall all Ohci Interface.
+
+ @param Controller Controller handle.
+ @param This Protocol instance pointer.
+
+**/
+VOID
+OhciCleanDevUp (
+ IN EFI_HANDLE Controller,
+ IN EFI_USB2_HC_PROTOCOL *This
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+
+ //
+ // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller
+ //
+ Ohc = OHC_FROM_USB2_HC_PROTO (This);
+ OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
+
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ &Ohc->Usb2Hc
+ );
+
+ OhciFreeAllAsyncReq (Ohc);
+ OhciDestoryFrameList (Ohc);
+
+ //
+ // Restore original PCI attributes
+ //
+ Ohc->PciIo->Attributes (
+ Ohc->PciIo,
+ EfiPciIoAttributeOperationSet,
+ Ohc->OriginalPciAttributes,
+ NULL
+ );
+
+ OhciFreeDev (Ohc);
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+}
+
+/**
+ One notified function to stop the Host Controller when gBS->ExitBootServices() called.
+
+ @param Event Pointer to this event
+ @param Context Event hanlder private data
+
+**/
+VOID
+EFIAPI
+OhcExitBootService (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ USB_HC_DEV *Ohc;
+
+ Ohc = (USB_HC_DEV *) Context;
+
+ //
+ // Stop the Host Controller
+ //
+ OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
+
+ //
+ // Reset the Host Controller
+ //
+ OhciSetRegBit (Ohc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);
+ gBS->Stall (OHC_ROOT_PORT_RECOVERY_STALL);
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+}
+
+/**
+ Starting the Usb OHCI Driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB_HC_DEV *Ohc;
+ UINT64 Supports;
+ UINT64 OriginalPciAttributes;
+ BOOLEAN PciAttributesSaved;
+ UINT32 CmdStatus;
+ UINT32 Buffer;
+
+ //
+ // Open PCIIO, then enable the EHC device and turn off emulation
+ //
+ Ohc = NULL;
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "FAIL! OpenProtocol\n"));
+ return Status;
+ }
+
+ PciAttributesSaved = FALSE;
+ //
+ // Save original PCI attributes
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &OriginalPciAttributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "FAIL! Attributes\n"));
+ goto CLOSE_PCIIO;
+ }
+ PciAttributesSaved = TRUE;
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ if (!EFI_ERROR (Status)) {
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "OhcDriverBindingStart: failed to enable controller\n"));
+ goto CLOSE_PCIIO;
+ }
+
+ gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
+
+ Ohc = OhciAllocateDev (PciIo, OriginalPciAttributes);
+
+ if (Ohc == NULL) {
+ DEBUG ((EFI_D_ERROR, "FAIL OhciAllocateDev \n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto CLOSE_PCIIO;
+ }
+
+ DEBUG ((EFI_D_ERROR, "OHCI SetTimer\n"));
+ Status = gBS->SetTimer (
+ Ohc->AsyncIntMonitor,
+ TimerPeriodic,
+ OHC_ASYNC_POLL_INTERVAL
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto FREE_OHC;
+ }
+
+ //
+ // Install USB2_HC_PROTOCOL
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiUsb2HcProtocolGuid,
+ &Ohc->Usb2Hc,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto FREE_OHC;
+ }
+
+ //
+ // Create event to stop the HC when exit boot service.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ OhcExitBootService,
+ Ohc,
+ &gEfiEventExitBootServicesGuid,
+ &Ohc->ExitBootServiceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto UNINSTALL_USBHC;
+ }
+
+ //
+ // Install the component name protocol
+ //
+ Ohc->CtrlNameTable = NULL;
+
+ AddUnicodeString2 (
+ "eng",
+ gOhciComponentName.SupportedLanguages,
+ &Ohc->CtrlNameTable,
+ L"Usb Universal Host Controller",
+ TRUE
+ );
+ AddUnicodeString2 (
+ "en",
+ gOhciComponentName2.SupportedLanguages,
+ &Ohc->CtrlNameTable,
+ L"Usb Universal Host Controller",
+ FALSE
+ );
+
+
+ //
+ // Start the OHCI hardware, also set its reclamation point to 64 bytes
+ //
+ //take ownership
+
+// OhcDumpRegs(Ohc);
+
+ CmdStatus = OhciReadReg(Ohc, HC_COM_STATUS_OFFSET);
+ OhciWriteReg(Ohc, HC_COM_STATUS_OFFSET, (CmdStatus | (1<<3)));
+
+ do
+ {
+ gBS->Stall(1000);
+ CmdStatus = OhciReadReg(Ohc, HC_COM_STATUS_OFFSET);
+ } while((CmdStatus & (1<<3)));
+
+ //interrupt disable
+ OhciWriteReg(Ohc, HC_INT_DISABLE_OFFSET, 0xFFFFFFFF);
+
+ //interrupt status clear
+ CmdStatus = OhciReadReg(Ohc, HC_INT_STATUS_OFFSET);
+ OhciWriteReg(Ohc, HC_INT_STATUS_OFFSET, CmdStatus);
+
+ //frame interval
+ CmdStatus = OhciReadReg(Ohc, HC_FMINTERVAL_OFFSET);
+ CmdStatus &= 0x8000FFFF;
+ CmdStatus |= (0x800<<16); //256*8
+ OhciWriteReg(Ohc, HC_FMINTERVAL_OFFSET, CmdStatus);
+
+ //set hcca base
+ //
+ // Allocate and Init Host Controller's Frame List Entry
+ //
+
+ #if 1
+ Buffer = UsbHcAllocateMem (Ohc->MemPool, sizeof(OHCI_HCCA));
+ ZeroMem (Buffer, sizeof(OHCI_HCCA));
+ OhciWriteReg(Ohc, HC_HCCA_OFFSET, (UINT32)Buffer);
+ #else
+ Status = OhciInitFrameList (Ohc);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "FAIL OhciInitFrameList\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_OHC;
+ }
+ #endif
+
+ //Set opertional state
+ CmdStatus = OhciReadReg(Ohc, HC_CONTROL_OFFSET);
+ CmdStatus &= ~(3<<6);
+ CmdStatus |= (2<<6);
+ OhciWriteReg(Ohc, HC_CONTROL_OFFSET, CmdStatus);
+
+ //setPowerSwitchingMode off
+ CmdStatus = OhciReadReg(Ohc, HC_RH_DESCRIPTORA_OFFSET);
+ CmdStatus &= ~(1<<8);
+ OhciWriteReg(Ohc, HC_RH_DESCRIPTORA_OFFSET, CmdStatus);
+
+ //Set global power
+ CmdStatus = OhciReadReg(Ohc, HC_RH_STATUS_OFFSET);
+ CmdStatus |= (1<<16);
+ OhciWriteReg(Ohc, HC_RH_STATUS_OFFSET, CmdStatus);
+
+ OhcDumpRegs(Ohc);
+
+ DEBUG((EFI_D_INFO, "--%a(EFI_SUCCESS):%d\n", __FUNCTION__, __LINE__));
+
+ return EFI_SUCCESS;
+
+UNINSTALL_USBHC:
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ &Ohc->Usb2Hc,
+ NULL
+ );
+
+FREE_OHC:
+ OhciFreeDev (Ohc);
+
+CLOSE_PCIIO:
+ if (PciAttributesSaved) {
+ //
+ // Restore original PCI attributes
+ //
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSet,
+ OriginalPciAttributes,
+ NULL
+ );
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return Status;
+}
+
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+EFIAPI
+OhciDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ EFI_USB2_HC_PROTOCOL *Usb2Hc;
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **) &Usb2Hc,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ //
+ // Test whether the Controller handler passed in is a valid
+ // Usb controller handle that should be supported, if not,
+ // return the error status directly
+ //
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OhciCleanDevUp (Controller, Usb2Hc);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return EFI_SUCCESS;
+}
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/Ohci.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/Ohci.h
new file mode 100644
index 000000000..e84e5e868
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/Ohci.h
@@ -0,0 +1,229 @@
+/** @file
+
+ The definition for OHCI driver model and HC protocol routines.
+
+Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
+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 _EFI_OHCI_H_
+#define _EFI_OHCI_H_
+
+
+#include <Uefi.h>
+
+#include <Protocol/Usb2HostController.h>
+#include <Protocol/UsbHostController.h>
+#include <Protocol/PciIo.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+typedef struct _USB_HC_DEV USB_HC_DEV;
+
+#include "UsbHcMem.h"
+#include "OhciQueue.h"
+#include "OhciReg.h"
+#include "OhciSched.h"
+#include "OhciDebug.h"
+#include "ComponentName.h"
+
+//
+// OHC timeout experience values
+//
+
+#define OHC_1_MICROSECOND 1
+#define OHC_1_MILLISECOND (1000 * OHC_1_MICROSECOND)
+#define OHC_1_SECOND (1000 * OHC_1_MILLISECOND)
+
+//
+// OHCI register operation timeout, set by experience
+//
+#define OHC_GENERIC_TIMEOUT OHC_1_SECOND
+
+//
+// Wait for force global resume(FGR) complete, refers to
+// specification[OHCI11-2.1.1]
+//
+#define OHC_FORCE_GLOBAL_RESUME_STALL (20 * OHC_1_MILLISECOND)
+
+//
+// Wait for roothub port reset and recovery, reset stall
+// is set by experience, and recovery stall refers to
+// specification[OHCI11-2.1.1]
+//
+#define OHC_ROOT_PORT_RESET_STALL (50 * OHC_1_MILLISECOND)
+#define OHC_ROOT_PORT_RECOVERY_STALL (10 * OHC_1_MILLISECOND)
+
+//
+// Sync and Async transfer polling interval, set by experience,
+// and the unit of Async is 100us.
+//
+#define OHC_SYNC_POLL_INTERVAL (1 * OHC_1_MILLISECOND)
+#define OHC_ASYNC_POLL_INTERVAL (50 * 10000UL)
+
+//
+// OHC raises TPL to TPL_NOTIFY to serialize all its operations
+// to protect shared data structures.
+//
+#define OHCI_TPL TPL_NOTIFY
+
+#define USB_HC_DEV_SIGNATURE SIGNATURE_32 ('u', 'h', 'c', 'i')
+
+#pragma pack(1)
+typedef struct {
+ UINT8 ProgInterface;
+ UINT8 SubClassCode;
+ UINT8 BaseCode;
+} USB_CLASSC;
+#pragma pack()
+
+#define OHC_FROM_USB2_HC_PROTO(This) CR(This, USB_HC_DEV, Usb2Hc, USB_HC_DEV_SIGNATURE)
+
+//
+// USB_HC_DEV support the OHCI hardware controller. It schedules
+// the asynchronous interrupt transfer with the same method as
+// EHCI: a reversed tree structure. For synchronous interrupt,
+// control and bulk transfer, it uses three static queue head to
+// schedule them. SyncIntQh is for interrupt transfer. LsCtrlQh is
+// for LOW speed control transfer, and FsCtrlBulkQh is for FULL
+// speed control or bulk transfer. This is because FULL speed contrl
+// or bulk transfer can reclaim the unused bandwidth. Some USB
+// device requires this bandwidth reclamation capability.
+//
+struct _USB_HC_DEV {
+ UINT32 Signature;
+ EFI_USB2_HC_PROTOCOL Usb2Hc;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 OriginalPciAttributes;
+
+ //
+ // Schedule data structures
+ //
+ OHCI_HCCA *Hcca;
+ UINT32 *HccaMapping;
+
+
+ UINT32 *FrameBase; // the buffer pointed by this pointer is used to store pci bus address of the QH descriptor.
+ UINT32 *FrameBaseHostAddr; // the buffer pointed by this pointer is used to store host memory address of the QH descriptor.
+
+ OHCI_TD_SW *CtrlQh;
+ OHCI_TD_SW *IntrQh;
+
+ OHCI_TD_HW *LastTd;
+
+ OHCI_ED_HW *EdHw[15];
+
+ UINT32 *Destory;
+ UINT32 DestroySize;
+ //
+ // Structures to maintain asynchronus interrupt transfers.
+ // When asynchronous interrutp transfer is unlinked from
+ // the frame list, the hardware may still hold a pointer
+ // to it. To synchronize with hardware, its resoureces are
+ // released in two steps using Recycle and RecycleWait.
+ // Check the asynchronous interrupt management routines.
+ //
+ LIST_ENTRY AsyncIntList;
+ EFI_EVENT AsyncIntMonitor;
+ OHCI_ASYNC_REQUEST *Recycle;
+ OHCI_ASYNC_REQUEST *RecycleWait;
+
+
+ UINTN RootPorts;
+ USBHC_MEM_POOL *MemPool;
+ EFI_UNICODE_STRING_TABLE *CtrlNameTable;
+ VOID *FrameMapping;
+
+ //
+ // ExitBootServicesEvent is used to stop the EHC DMA operation
+ // after exit boot service.
+ //
+ EFI_EVENT ExitBootServiceEvent;
+};
+
+extern EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gOhciComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gOhciComponentName2;
+
+/**
+ Test to see if this driver supports ControllerHandle. Any
+ ControllerHandle that has UsbHcProtocol installed will be supported.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @return EFI_SUCCESS This driver supports this device.
+ @return EFI_UNSUPPORTED This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starting the Usb OHCI Driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to test.
+ @param RemainingDevicePath Not used.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
+
+**/
+EFI_STATUS
+EFIAPI
+OhciDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ @param This Protocol instance pointer.
+ @param Controller Handle of device to stop driver on.
+ @param NumberOfChildren Number of Children in the ChildHandleBuffer.
+ @param ChildHandleBuffer List of handles for the children we need to stop.
+
+ @return EFI_SUCCESS
+ @return others
+
+**/
+EFI_STATUS
+EFIAPI
+OhciDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDebug.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDebug.c
new file mode 100644
index 000000000..fca45cc06
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDebug.c
@@ -0,0 +1,181 @@
+/** @file
+
+ This file provides the information dump support for Ohci when in debug mode.
+
+Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+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 "Ohci.h"
+
+
+#ifdef EFI_D_INIT
+#undef EFI_D_INIT
+#define EFI_D_INIT EFI_D_INFO
+#endif
+
+/**
+ Dump the content of QH structure.
+
+ @param QhSw Pointer to software QH structure.
+
+**/
+#if 0
+VOID
+OhciDumpQh (
+ IN OHCI_QH_SW *QhSw
+ )
+{
+ DEBUG ((EFI_D_INFO, "&QhSw @ 0x%p\n", QhSw));
+ DEBUG ((EFI_D_INFO, "QhSw.NextQh - 0x%p\n", QhSw->NextQh));
+ DEBUG ((EFI_D_INFO, "QhSw.TDs - 0x%p\n", QhSw->TDs));
+ DEBUG ((EFI_D_INFO, "QhSw.QhHw:\n"));
+ DEBUG ((EFI_D_INFO, " Horizon Link - %x\n", QhSw->QhHw.HorizonLink));
+ DEBUG ((EFI_D_INFO, " Vertical Link - %x\n\n", QhSw->QhHw.VerticalLink));
+}
+#endif
+
+/**
+ Dump the content of TD structure.
+
+ @param TdSw Pointer to software TD structure.
+
+**/
+VOID
+OhciDumpTdHw (
+ IN OHCI_TD_HW *TdSw
+ )
+{
+ OHCI_TD_HW *CurTdSw;
+
+ DEBUG ((EFI_D_INIT, "\n+++OhciDumpTds()\n"));
+
+ CurTdSw = TdSw;
+
+ while (CurTdSw != NULL) {
+ DEBUG ((EFI_D_INIT, " TdHw @ 0x%p\n", CurTdSw));
+ DEBUG ((EFI_D_INIT, "TdHw.NextTd - 0x%p\n", CurTdSw->next_td));
+ DEBUG ((EFI_D_INIT, "TdHw.StartPtr - 0x%p\n", CurTdSw->current_buf_ptr));
+ DEBUG ((EFI_D_INIT, "TdHw.EndPtr - 0x%p\n", CurTdSw->buffer_end));
+ DEBUG ((EFI_D_INIT, "gtd_info:\n"));
+ DEBUG ((EFI_D_INIT, " buffer_rounding - 0x%x\n", CurTdSw->gtd_info.b.buffer_rounding));
+ DEBUG ((EFI_D_INIT, " pid - 0x%x\n", CurTdSw->gtd_info.b.pid));
+ DEBUG ((EFI_D_INIT, " error_count - 0x%x\n", CurTdSw->gtd_info.b.error_count));
+ DEBUG ((EFI_D_INIT, " condition_code - 0x%x\n", CurTdSw->gtd_info.b.condition_code));
+ DEBUG ((EFI_D_INIT, " data_toggle - 0x%x\n", CurTdSw->gtd_info.b.data_toggle));
+
+ CurTdSw = CurTdSw->next_td;
+ }
+
+ DEBUG ((EFI_D_INIT, "---OhciDumpTds()\n"));
+}
+
+VOID
+OhciDumpEd (
+ IN OHCI_ED_HW *EdHw
+ )
+{
+ DEBUG ((EFI_D_INIT, "\n+++OhciDumpEd()\n"));
+
+ DEBUG ((EFI_D_INIT, "ed_info:\n"));
+ DEBUG ((EFI_D_INIT, " func_addr - 0x%x\n", EdHw->ed_info.b.func_addr));
+ DEBUG ((EFI_D_INIT, " ep_num - 0x%x\n", EdHw->ed_info.b.ep_num));
+ DEBUG ((EFI_D_INIT, " direction - 0x%x\n", EdHw->ed_info.b.direction));
+ DEBUG ((EFI_D_INIT, " speed - 0x%x\n", EdHw->ed_info.b.speed));
+ DEBUG ((EFI_D_INIT, " skip - 0x%x\n", EdHw->ed_info.b.skip));
+ DEBUG ((EFI_D_INIT, " format - 0x%x\n", EdHw->ed_info.b.format));
+ DEBUG ((EFI_D_INIT, " mps - 0x%x\n", EdHw->ed_info.b.mps));
+
+ OhciDumpTdHw(EdHw->head_td_ptr);
+
+ DEBUG ((EFI_D_INIT, "---OhciDumpEd()\n\n"));
+}
+
+VOID
+OhciDumpSWTds (
+ IN OHCI_TD_SW *TdSw
+ )
+{
+ OHCI_TD_SW *CurTdSw;
+ OHCI_TD_HW *TdHw;
+
+ DEBUG ((EFI_D_INIT, "\n+++OhciDumpSWTds()\n"));
+
+ CurTdSw = TdSw;
+ TdHw = CurTdSw->TdHw;
+
+ while (TdHw != NULL) {
+ DEBUG ((EFI_D_INIT, " TdHw @ 0x%p\n", TdHw));
+ DEBUG ((EFI_D_INIT, "TdHw.NextTd - 0x%p\n", TdHw->next_td));
+ DEBUG ((EFI_D_INIT, "TdHw.StartPtr - 0x%p\n", TdHw->current_buf_ptr));
+ DEBUG ((EFI_D_INIT, "TdHw.EndPtr - 0x%p\n", TdHw->buffer_end));
+ DEBUG ((EFI_D_INIT, "TdSw.DataLen - 0x%p\n", CurTdSw->DataLen));
+ DEBUG ((EFI_D_INIT, "gtd_info:\n"));
+ DEBUG ((EFI_D_INIT, " buffer_rounding - 0x%x\n", TdHw->gtd_info.b.buffer_rounding));
+ DEBUG ((EFI_D_INIT, " pid - 0x%x\n", TdHw->gtd_info.b.pid));
+ DEBUG ((EFI_D_INIT, " error_count - 0x%x\n", TdHw->gtd_info.b.error_count));
+ DEBUG ((EFI_D_INIT, " condition_code - 0x%x\n", TdHw->gtd_info.b.condition_code));
+ DEBUG ((EFI_D_INIT, " data_toggle - 0x%x\n", TdHw->gtd_info.b.data_toggle));
+
+ CurTdSw = CurTdSw->NextTd;
+ TdHw = CurTdSw->TdHw;
+ }
+
+ DEBUG ((EFI_D_INIT, "---OhciDumpSWTds()\n\n"));
+}
+
+VOID
+OhcDumpRegs (
+ IN USB_HC_DEV *Ohc
+ )
+{
+ UINT8 Index;
+
+ DEBUG ((EFI_D_INIT, " HC_REVISION_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_REVISION_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_CONTROL_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_CONTROL_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_COM_STATUS_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_COM_STATUS_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_HCCA_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_HCCA_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_FMINTERVAL_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_FMINTERVAL_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_INT_DISABLE_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_INT_DISABLE_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_INT_STATUS_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_INT_STATUS_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_CTRL_HEADED_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_CTRL_HEADED_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_CTRL_CURRED_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_CTRL_CURRED_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_BULK_HEADED_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_BULK_HEADED_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_BULK_CURRED_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_BULK_CURRED_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_RH_STATUS_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_RH_STATUS_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_RH_DESCRIPTORA_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_RH_DESCRIPTORA_OFFSET)));
+ DEBUG ((EFI_D_INIT, " HC_RH_DESCRIPTORB_OFFSET = 0x%08x\n", OhciReadReg (Ohc, HC_RH_DESCRIPTORB_OFFSET)));
+
+ for (Index = 0; Index <3; Index++) {
+ DEBUG ((EFI_D_INIT, " HC_PORT_STATUS_OFFSET(%d) = 0x%08x\n", Index, OhciReadReg (Ohc, HC_PORT_STATUS_OFFSET + (4 * Index))));
+ }
+}
+
+VOID
+OhcDumpRequest (
+ IN EFI_USB_DEVICE_REQUEST *Request
+ )
+{
+ DEBUG ((EFI_D_INIT, "RequestType = 0x%X\n", Request->RequestType));
+ DEBUG ((EFI_D_INIT, "Request = 0x%X\n", Request->Request));
+ DEBUG ((EFI_D_INIT, "Value = 0x%X\n", Request->Value));
+ DEBUG ((EFI_D_INIT, "Index = 0x%X\n", Request->Index));
+ DEBUG ((EFI_D_INIT, "Length = 0x%X\n", Request->Length));
+}
+
+VOID
+OhcDumpResult (
+ IN OHCI_QH_RESULT *Result
+ )
+{
+ DEBUG ((EFI_D_INIT, "Result = 0x%X\n", Result->Result));
+ DEBUG ((EFI_D_INIT, "Complete = 0x%X\n", Result->Complete));
+ DEBUG ((EFI_D_INIT, "NextToggle = 0x%X\n", Result->NextToggle));
+} \ No newline at end of file
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDebug.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDebug.h
new file mode 100644
index 000000000..8155fcc7d
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDebug.h
@@ -0,0 +1,51 @@
+/** @file
+
+ This file contains the definination for host controller debug support routines
+
+Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+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 _EFI_OHCI_DEBUG_H_
+#define _EFI_OHCI_DEBUG_H_
+
+
+/**
+ Dump the content of QH structure.
+
+ @param QhSw Pointer to software QH structure.
+
+ @return None.
+
+**/
+VOID
+OhciDumpQh (
+ IN OHCI_QH_SW *QhSw
+ );
+
+
+/**
+ Dump the content of TD structure.
+
+ @param TdSw Pointer to software TD structure.
+
+ @return None.
+
+**/
+VOID
+OhciDumpTds (
+ IN OHCI_TD_HW *TdSw
+ );
+
+VOID
+OhcDumpRegs (
+ IN USB_HC_DEV *Ohc
+ );
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDxe.inf
new file mode 100644
index 000000000..344e9cd9c
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciDxe.inf
@@ -0,0 +1,88 @@
+## @file
+#
+# Component Description File For OhciDxe Module.
+#
+# OhciDxe driver is responsible for managing the behavior of OHCI controller.
+# It implements the interfaces of monitoring the status of all ports and transferring
+# Control, Bulk, Interrupt and Isochronous requests to Usb1.x device
+#
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# 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 = OhciDxe
+ FILE_GUID = 2FB92EFA-2EE0-4bae-9EB6-7464125E1EF7
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = OhciDriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gOhciDriverBinding
+# COMPONENT_NAME = gOhciComponentName
+# COMPONENT_NAME2 = gOhciComponentName2
+#
+
+[Sources]
+ OhciSched.c
+ OhciDebug.c
+ UsbHcMem.h
+ OhciDebug.h
+ OhciQueue.c
+ OhciReg.c
+ UsbHcMem.c
+ OhciQueue.h
+ Ohci.c
+ Ohci.h
+ OhciReg.h
+ OhciSched.h
+ ComponentName.c
+ ComponentName.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport ## SOMETIME_CONSUMES (enable/disable usb legacy support.)
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+
+[Guids]
+ gEfiEventExitBootServicesGuid ## PRODUCES ## Event
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gEfiUsb2HcProtocolGuid ## BY_START
+ gEfiCpuArchProtocolGuid
+
+# [Event]
+# ##
+# # Periodic timer event for checking the result of interrupt transfer execution.
+# #
+# EVENT_TYPE_PERIODIC_TIMER ## PRODUCES
+#
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciQueue.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciQueue.c
new file mode 100644
index 000000000..f25da6c41
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciQueue.c
@@ -0,0 +1,993 @@
+/** @file
+
+ The OHCI register operation routines.
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "Ohci.h"
+
+
+/**
+ Map address of request structure buffer.
+
+ @param Ohc The OHCI device.
+ @param Request The user request buffer.
+ @param MappedAddr Mapped address of request.
+ @param Map Identificaion of this mapping to return.
+
+ @return EFI_SUCCESS Success.
+ @return EFI_DEVICE_ERROR Fail to map the user request.
+
+**/
+EFI_STATUS
+OhciMapUserRequest (
+ IN USB_HC_DEV *Ohc,
+ IN OUT VOID *Request,
+ OUT UINT8 **MappedAddr,
+ OUT VOID **Map
+ )
+{
+ EFI_STATUS Status;
+ UINTN Len;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+
+#if 1
+ Len = sizeof (EFI_USB_DEVICE_REQUEST);
+ Status = Ohc->PciIo->Map (
+ Ohc->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ Request,
+ &Len,
+ &PhyAddr,
+ Map
+ );
+
+ if (!EFI_ERROR (Status)) {
+ *MappedAddr = (UINT8 *) (UINTN) PhyAddr;
+ }
+#else
+ Len = sizeof (EFI_USB_DEVICE_REQUEST);
+ Status = Ohc->PciIo->Map (
+ Ohc->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ Request,
+ &Len,
+ &PhyAddr,
+ Map
+ );
+
+ if (!EFI_ERROR (Status)) {
+ *MappedAddr = (UINT8 *) (UINTN) PhyAddr;
+ }
+#endif
+ return Status;
+}
+
+
+/**
+ Map address of user data buffer.
+
+ @param Ohc The OHCI device.
+ @param Direction Direction of the data transfer.
+ @param Data The user data buffer.
+ @param Len Length of the user data.
+ @param PktId Packet identificaion.
+ @param MappedAddr Mapped address to return.
+ @param Map Identificaion of this mapping to return.
+
+ @return EFI_SUCCESS Success.
+ @return EFI_DEVICE_ERROR Fail to map the user data.
+
+**/
+EFI_STATUS
+OhciMapUserData (
+ IN USB_HC_DEV *Ohc,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN VOID *Data,
+ IN OUT UINTN *Len,
+ OUT UINT8 *PktId,
+ OUT UINT8 **MappedAddr,
+ OUT VOID **Map
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+
+ Status = EFI_SUCCESS;
+#if 1
+ switch (Direction) {
+ case EfiUsbDataIn:
+ //
+ // BusMasterWrite means cpu read
+ //
+ *PktId = INPUT_PACKET_ID;
+ Status = Ohc->PciIo->Map (
+ Ohc->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ Data,
+ Len,
+ &PhyAddr,
+ Map
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ DEBUG((EFI_D_INIT, "Read Mapped : %p\n", *Map));
+ *MappedAddr = (UINT8 *) (UINTN) PhyAddr;
+ break;
+
+ case EfiUsbDataOut:
+ *PktId = OUTPUT_PACKET_ID;
+ Status = Ohc->PciIo->Map (
+ Ohc->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ Data,
+ Len,
+ &PhyAddr,
+ Map
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ DEBUG((EFI_D_INIT, "Write Mapped : %p\n", *Map));
+ *MappedAddr = (UINT8 *) (UINTN) PhyAddr;
+ break;
+
+ case EfiUsbNoData:
+ if ((Len != NULL) && (*Len != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ DEBUG((EFI_D_INIT, "No Mapped : %p\n", *Map));
+ *PktId = OUTPUT_PACKET_ID;
+ *MappedAddr = NULL;
+ *Map = NULL;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+#else
+ switch (Direction) {
+ case EfiUsbDataIn:
+ //
+ // BusMasterWrite means cpu read
+ //
+ *PktId = INPUT_PACKET_ID;
+ Status = Ohc->PciIo->Map (
+ Ohc->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ Data,
+ Len,
+ &PhyAddr,
+ Map
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+ *MappedAddr = (UINT8 *) (UINTN) PhyAddr;
+ break;
+
+ case EfiUsbDataOut:
+ *PktId = OUTPUT_PACKET_ID;
+ Status = Ohc->PciIo->Map (
+ Ohc->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ Data,
+ Len,
+ &PhyAddr,
+ Map
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+ *MappedAddr = (UINT8 *) (UINTN) PhyAddr;
+ break;
+
+ case EfiUsbNoData:
+ if ((Len != NULL) && (*Len != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+
+ *PktId = OUTPUT_PACKET_ID;
+ *MappedAddr = NULL;
+ *Map = NULL;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+#endif
+EXIT:
+ return Status;
+}
+
+
+/**
+ Link the TD To QH.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head for the TD to link to.
+ @param Td The TD to link.
+
+**/
+VOID
+OhciLinkTdToQh (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ED_HW *Ed,
+ IN UINT8 Class
+ )
+{
+#if 1
+ UINT32 cmd;
+
+ if(Class == HC_CLASS_CONTROL) //Controll
+ {
+ /*
+ cmd = OhciReadReg(Ohc, HC_CONTROL_OFFSET);
+ cmd &= ~(1<<5);
+ OhciWriteReg(Ohc, HC_CONTROL_OFFSET, cmd); */
+
+ cmd = OhciReadReg(Ohc, HC_COM_STATUS_OFFSET);
+ cmd |= (1<<1);
+ OhciWriteReg(Ohc, HC_COM_STATUS_OFFSET, cmd);
+
+ OhciWriteReg(Ohc, HC_CTRL_HEADED_OFFSET, Ed);
+
+ cmd = OhciReadReg(Ohc, HC_CONTROL_OFFSET);
+ cmd |= (1<<4);
+ OhciWriteReg(Ohc, HC_CONTROL_OFFSET, cmd);
+ }
+ else//Interrupt
+ {/*
+ cmd = OhciReadReg(Ohc, HC_CONTROL_OFFSET);
+ cmd &= ~(1<<4);
+ OhciWriteReg(Ohc, HC_CONTROL_OFFSET, cmd);
+ */
+ cmd = OhciReadReg(Ohc, HC_COM_STATUS_OFFSET);
+ cmd |= (1<<2);
+ OhciWriteReg(Ohc, HC_COM_STATUS_OFFSET, cmd);
+
+ OhciWriteReg(Ohc, HC_BULK_HEADED_OFFSET, Ed);
+
+ cmd = OhciReadReg(Ohc, HC_CONTROL_OFFSET);
+ cmd |= (1<<5);
+ OhciWriteReg(Ohc, HC_CONTROL_OFFSET, cmd);
+ }
+#else
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+
+ PhyAddr = UsbHcGetPciAddressForHostMem (Ohc->MemPool, Td, sizeof (OHCI_TD_HW));
+
+ ASSERT ((Qh != NULL) && (Td != NULL));
+
+ Qh->QhHw.VerticalLink = QH_VLINK (PhyAddr, FALSE);
+ Qh->TDs = (VOID *) Td;
+#endif
+}
+
+
+/**
+ Unlink TD from the QH.
+
+ @param Qh The queue head to unlink from.
+ @param Td The TD to unlink.
+
+**/
+VOID
+OhciUnlinkTdFromQh (
+ IN OHCI_QH_SW *Qh,
+ IN OHCI_TD_HW *Td
+ )
+{
+#if 1
+#else
+ ASSERT ((Qh != NULL) && (Td != NULL));
+
+ Qh->QhHw.VerticalLink = QH_VLINK (NULL, TRUE);
+ Qh->TDs = NULL;
+#endif
+}
+
+
+/**
+ Append a new TD To the previous TD.
+
+ @param Ohc The OHCI device.
+ @param PrevTd Previous OHCI_TD_HW to be linked to.
+ @param ThisTd TD to link.
+
+**/
+VOID
+OhciAppendTd (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_TD_HW *PrevTd,
+ IN OHCI_TD_HW *ThisTd
+ )
+{
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+
+ //PhyAddr = UsbHcGetPciAddressForHostMem (Ohc->MemPool, ThisTd, sizeof (OHCI_TD_HW));
+
+ ASSERT ((PrevTd != NULL) && (ThisTd != NULL));
+
+#if 1
+ PrevTd->next_td = (VOID *) ThisTd;
+#else
+ PrevTd->TdHw.NextLink = TD_LINK (PhyAddr, TRUE, FALSE);
+ PrevTd->NextTd = (VOID *) ThisTd;
+#endif
+}
+
+
+/**
+ Delete a list of TDs.
+
+ @param Ohc The OHCI device.
+ @param FirstTd TD link list head.
+
+ @return None.
+
+**/
+VOID
+OhciDestoryTds (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_TD_SW *FirstTd
+ )
+{
+ OHCI_TD_SW *NextTd;
+ OHCI_TD_SW *ThisTd;
+
+ DEBUG((EFI_D_INIT, "+++OhciDestoryTds()\n"));
+
+ NextTd = FirstTd;
+
+ while (NextTd != NULL) {
+ ThisTd = NextTd;
+ NextTd = ThisTd->NextTd;
+ if(ThisTd->TdHw)
+ {
+ DEBUG((EFI_D_INIT, "Destroy TDHW : %p\n", ThisTd->TdHw));
+ UsbHcFreeMem (Ohc->MemPool, ThisTd->TdHw, sizeof (OHCI_TD_HW));
+ }
+ DEBUG((EFI_D_INIT, "Destroy THSW : %p\n", ThisTd));
+ UsbHcFreeMem (Ohc->MemPool, ThisTd, sizeof (OHCI_TD_SW));
+ }
+
+ DEBUG((EFI_D_INIT, "---OhciDestoryTds()\n"));
+}
+
+
+/**
+ Create an initialize a new queue head.
+
+ @param Ohc The OHCI device.
+ @param Interval The polling interval for the queue.
+
+ @return The newly created queue header.
+
+**/
+OHCI_QH_SW *
+OhciCreateQh (
+ IN USB_HC_DEV *Ohc,
+ IN UINTN Interval
+ )
+{
+ OHCI_QH_SW *Qh;
+#if 1
+#else
+ Qh = UsbHcAllocateMem (Ohc->MemPool, sizeof (OHCI_QH_SW));
+
+ if (Qh == NULL) {
+ return NULL;
+ }
+
+ Qh->QhHw.HorizonLink = QH_HLINK (NULL, TRUE);
+ Qh->QhHw.VerticalLink = QH_VLINK (NULL, TRUE);
+ Qh->Interval = OhciConvertPollRate(Interval);
+ Qh->TDs = NULL;
+ Qh->NextQh = NULL;
+#endif
+ return Qh;
+}
+
+
+/**
+ Create and intialize a TD.
+
+ @param Ohc The OHCI device.
+
+ @return The newly allocated and initialized TD.
+
+**/
+OHCI_TD_HW *
+OhciCreateTd (
+ IN USB_HC_DEV *Ohc
+ )
+{
+ OHCI_TD_HW *Td;
+
+ Td = UsbHcAllocateMem (Ohc->MemPool, sizeof (OHCI_TD_HW));
+ if (Td == NULL) {
+ return NULL;
+ }
+
+ Td->current_buf_ptr = NULL;
+ Td->next_td = NULL;
+ Td->buffer_end = NULL;
+
+ return Td;
+}
+
+
+/**
+ Create and initialize a TD for Setup Stage of a control transfer.
+
+ @param Ohc The OHCI device.
+ @param DevAddr Device address.
+ @param Request A pointer to cpu memory address of Device request.
+ @param RequestPhy A pointer to pci memory address of Device request.
+ @param IsLow Full speed or low speed.
+
+ @return The created setup Td Pointer.
+
+**/
+OHCI_TD_HW *
+OhciCreateSetupTd (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DevAddr,
+ IN UINT8 *Request,
+ IN UINT8 *RequestPhy,
+ IN BOOLEAN IsLow
+ )
+{
+ OHCI_TD_HW *Td;
+
+ Td = OhciCreateTd (Ohc);
+
+ if (Td == NULL) {
+ return NULL;
+ }
+#if 1
+ OhcDumpRequest(RequestPhy);
+ DEBUG((EFI_D_INIT, "LowSpeed : %d\n", IsLow));
+
+ Td->gtd_info.data = 0;
+ Td->gtd_info.b.buffer_rounding = 0;
+ Td->gtd_info.b.pid = SETUP_PACKET_ID;
+ Td->gtd_info.b.data_toggle = 2; // DATA0
+ Td->current_buf_ptr = (UINT32)RequestPhy;
+ Td->next_td = NULL;
+ Td->buffer_end = (UINT32)RequestPhy + sizeof (EFI_USB_DEVICE_REQUEST)-1;
+#else
+ Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);
+ Td->TdHw.ShortPacket = FALSE;
+ Td->TdHw.IsIsoch = FALSE;
+ Td->TdHw.IntOnCpl = FALSE;
+ Td->TdHw.ErrorCount = 0x03;
+ Td->TdHw.Status |= USBTD_ACTIVE;
+ Td->TdHw.DataToggle = 0;
+ Td->TdHw.EndPoint = 0;
+ Td->TdHw.LowSpeed = IsLow ? 1 : 0;
+ Td->TdHw.DeviceAddr = DevAddr & 0x7F;
+ Td->TdHw.MaxPacketLen = (UINT32) (sizeof (EFI_USB_DEVICE_REQUEST) - 1);
+ Td->TdHw.PidCode = SETUP_PACKET_ID;
+ Td->TdHw.DataBuffer = (UINT32) (UINTN) RequestPhy;
+
+ Td->Data = Request;
+ Td->DataLen = (UINT16) sizeof (EFI_USB_DEVICE_REQUEST);
+#endif
+ return Td;
+}
+
+
+/**
+ Create a TD for data.
+
+ @param Ohc The OHCI device.
+ @param DevAddr Device address.
+ @param Endpoint Endpoint number.
+ @param DataPtr A pointer to cpu memory address of Data buffer.
+ @param DataPhyPtr A pointer to pci memory address of Data buffer.
+ @param Len Data length.
+ @param PktId Packet ID.
+ @param Toggle Data toggle value.
+ @param IsLow Full speed or low speed.
+
+ @return Data Td pointer if success, otherwise NULL.
+
+**/
+OHCI_TD_HW *
+OhciCreateDataTd (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DevAddr,
+ IN UINT8 Endpoint,
+ IN UINT8 *DataPtr,
+ IN UINT8 *DataPhyPtr,
+ IN UINTN Len,
+ IN UINT8 PktId,
+ IN UINT8 Toggle,
+ IN BOOLEAN IsLow
+ )
+{
+ OHCI_TD_HW *Td;
+
+ //DEBUG((EFI_D_INIT, "+++OhciCreateDataTd(Len : %d)\n", Len));
+
+ //
+ // Code as length - 1, and the max valid length is 0x500
+ //
+ ASSERT (Len <= 0x500);
+
+ Td = OhciCreateTd (Ohc);
+
+ if (Td == NULL) {
+ return NULL;
+ }
+
+#if 1
+ Td->gtd_info.data = 0;
+ Td->gtd_info.b.buffer_rounding = 1; // may be smaller than the defined buffer
+ Td->gtd_info.b.pid = PktId;
+ Td->gtd_info.b.data_toggle = Toggle; // DATA1
+ Td->current_buf_ptr = (UINT32) (UINTN) DataPhyPtr;
+ Td->next_td = NULL;
+ Td->buffer_end = (UINT32) (UINTN) DataPhyPtr + Len-1;
+#else
+ Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);
+ Td->TdHw.ShortPacket = FALSE;
+ Td->TdHw.IsIsoch = FALSE;
+ Td->TdHw.IntOnCpl = FALSE;
+ Td->TdHw.ErrorCount = 0x03;
+ Td->TdHw.Status = USBTD_ACTIVE;
+ Td->TdHw.LowSpeed = IsLow ? 1 : 0;
+ Td->TdHw.DataToggle = Toggle & 0x01;
+ Td->TdHw.EndPoint = Endpoint & 0x0F;
+ Td->TdHw.DeviceAddr = DevAddr & 0x7F;
+ Td->TdHw.MaxPacketLen = (UINT32) (Len - 1);
+ Td->TdHw.PidCode = (UINT8) PktId;
+ Td->TdHw.DataBuffer = (UINT32) (UINTN) DataPhyPtr;
+
+ Td->Data = DataPtr;
+ Td->DataLen = (UINT16) Len;
+#endif
+
+ //DEBUG((EFI_D_INIT, "---OhciCreateDataTd()\n"));
+
+ return Td;
+}
+
+
+/**
+ Create TD for the Status Stage of control transfer.
+
+ @param Ohc The OHCI device.
+ @param DevAddr Device address.
+ @param PktId Packet ID.
+ @param IsLow Full speed or low speed.
+
+ @return Status Td Pointer.
+
+**/
+OHCI_TD_HW *
+OhciCreateStatusTd (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DevAddr,
+ IN UINT8 PktId,
+ IN BOOLEAN IsLow
+ )
+{
+ OHCI_TD_HW *Td;
+
+ Td = OhciCreateTd (Ohc);
+
+ if (Td == NULL) {
+ return NULL;
+ }
+
+#if 1
+ Td->gtd_info.data = 0;
+ Td->gtd_info.b.buffer_rounding = 1; // may be smaller than the defined buffer
+ Td->gtd_info.b.pid = PktId;
+ Td->gtd_info.b.data_toggle = 3; // DATA1
+ Td->current_buf_ptr = 0;
+ Td->next_td = 0;
+ Td->buffer_end = 0;
+#else
+ Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);
+ Td->TdHw.ShortPacket = FALSE;
+ Td->TdHw.IsIsoch = FALSE;
+ Td->TdHw.IntOnCpl = FALSE;
+ Td->TdHw.ErrorCount = 0x03;
+ Td->TdHw.Status |= USBTD_ACTIVE;
+ Td->TdHw.MaxPacketLen = 0x7FF; //0x7FF: there is no data (refer to OHCI spec)
+ Td->TdHw.DataToggle = 1;
+ Td->TdHw.EndPoint = 0;
+ Td->TdHw.LowSpeed = IsLow ? 1 : 0;
+ Td->TdHw.DeviceAddr = DevAddr & 0x7F;
+ Td->TdHw.PidCode = (UINT8) PktId;
+ Td->TdHw.DataBuffer = (UINT32) (UINTN) NULL;
+
+ Td->Data = NULL;
+ Td->DataLen = 0;
+#endif
+ return Td;
+}
+
+OHCI_ED_HW *
+OhciCreateEd (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DeviceAddr,
+ IN UINT32 *QH,
+ IN UINT8 MaxPacket,
+ IN BOOLEAN IsLow
+ )
+{
+ OHCI_ED_HW *Ed;
+
+ Ed = UsbHcAllocateMem (Ohc->MemPool, sizeof (OHCI_ED_HW));
+ if (Ed == NULL) {
+ return NULL;
+ }
+
+ Ed->ed_info.data = 0;
+ Ed->ed_info.b.func_addr = DeviceAddr;
+ Ed->ed_info.b.ep_num = 0;
+ Ed->ed_info.b.direction = 0;
+ Ed->ed_info.b.speed = IsLow?1:0; // speed
+ Ed->ed_info.b.format = 0; // gTD
+ Ed->ed_info.b.mps = MaxPacket;
+ Ed->tail_td_ptr = 0;
+ Ed->head_td_ptr = QH;
+ Ed->next_ed = 0;
+
+ return Ed;
+}
+
+/**
+ Create Tds list for Control Transfer.
+
+ @param Ohc The OHCI device.
+ @param DeviceAddr The device address.
+ @param DataPktId Packet Identification of Data Tds.
+ @param Request A pointer to cpu memory address of request structure buffer to transfer.
+ @param RequestPhy A pointer to pci memory address of request structure buffer to transfer.
+ @param Data A pointer to cpu memory address of user data buffer to transfer.
+ @param DataPhy A pointer to pci memory address of user data buffer to transfer.
+ @param DataLen Length of user data to transfer.
+ @param MaxPacket Maximum packet size for control transfer.
+ @param IsLow Full speed or low speed.
+
+ @return The Td list head for the control transfer.
+
+**/
+OHCI_ED_HW *
+OhciCreateCtrlTds (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DeviceAddr,
+ IN UINT8 DataPktId,
+ IN UINT8 *Request,
+ IN UINT8 *RequestPhy,
+ IN UINT8 *Data,
+ IN UINT8 *DataPhy,
+ IN UINTN DataLen,
+ IN UINT8 MaxPacket,
+ IN BOOLEAN IsLow
+ )
+{
+ OHCI_ED_HW *Ed;
+ OHCI_TD_HW *SetupTd;
+ OHCI_TD_HW *FirstDataTd;
+ OHCI_TD_HW *DataTd;
+ OHCI_TD_HW *PrevDataTd;
+ OHCI_TD_HW *StatusTd;
+ UINT8 DataToggle;
+ UINT8 StatusPktId;
+ UINTN ThisTdLen;
+
+
+ DataTd = NULL;
+ SetupTd = NULL;
+ FirstDataTd = NULL;
+ PrevDataTd = NULL;
+ StatusTd = NULL;
+
+ //
+ // Create setup packets for the transfer
+ //
+ SetupTd = OhciCreateSetupTd (Ohc, DeviceAddr, Request, RequestPhy, IsLow);
+
+ if (SetupTd == NULL) {
+ return NULL;
+ }
+
+ //
+ // Create data packets for the transfer
+ //
+ DataToggle = 1;
+ DEBUG((EFI_D_INIT, "Max Len %d, Dat Len ; %d\n", MaxPacket, DataLen));
+ while (DataLen > 0) {
+ //
+ // PktSize is the data load size in each Td.
+ //
+ ThisTdLen = (DataLen > MaxPacket ? MaxPacket : DataLen);
+
+ DataTd = OhciCreateDataTd (
+ Ohc,
+ DeviceAddr,
+ 0,
+ Data, //cpu memory address
+ DataPhy, //Pci memory address
+ ThisTdLen,
+ DataPktId,
+ (DataToggle + 2),
+ IsLow
+ );
+
+ if (DataTd == NULL) {
+ goto FREE_TD;
+ }
+
+ if (FirstDataTd == NULL) {
+ FirstDataTd = DataTd;
+ FirstDataTd->next_td = NULL;
+ } else {
+ OhciAppendTd (Ohc, PrevDataTd, DataTd);
+ }
+
+ DataToggle ^= 1;
+ PrevDataTd = DataTd;
+ Data += ThisTdLen;
+ DataPhy += ThisTdLen;
+ DataLen -= ThisTdLen;
+ }
+
+ //
+ // Status packet is on the opposite direction to data packets
+ //
+ if (OUTPUT_PACKET_ID == DataPktId) {
+ StatusPktId = INPUT_PACKET_ID;
+ } else {
+ StatusPktId = OUTPUT_PACKET_ID;
+ }
+
+ StatusTd = OhciCreateStatusTd (Ohc, DeviceAddr, StatusPktId, IsLow);
+
+ if (StatusTd == NULL) {
+ DEBUG((EFI_D_ERROR, "FAIL! OhciCreateStatusTd\n"));
+ goto FREE_TD;
+ }
+
+ //
+ // Link setup Td -> data Tds -> status Td together
+ //
+ if (FirstDataTd != NULL) {
+ OhciAppendTd (Ohc, SetupTd, FirstDataTd);
+ OhciAppendTd (Ohc, PrevDataTd, StatusTd);
+ } else {
+ OhciAppendTd (Ohc, SetupTd, StatusTd);
+ }
+
+ //iky
+
+ Ed = Ohc->EdHw[0];
+ Ed->ed_info.data = 0;
+ Ed->ed_info.b.func_addr = DeviceAddr;
+ Ed->ed_info.b.ep_num = 0;
+ Ed->ed_info.b.direction = 0;
+ Ed->ed_info.b.speed = IsLow?1:0; // speed
+ Ed->ed_info.b.format = 0; // gTD
+ Ed->ed_info.b.mps = MaxPacket;
+ Ed->tail_td_ptr = 0;
+ Ed->head_td_ptr = SetupTd;
+ Ed->next_ed = 0;
+
+ Ohc->LastTd = StatusTd;
+
+ return Ed;
+
+FREE_TD:
+ if (SetupTd != NULL) {
+ OhciDestoryTds (Ohc, SetupTd);
+ }
+
+ if (FirstDataTd != NULL) {
+ OhciDestoryTds (Ohc, FirstDataTd);
+ }
+
+ return NULL;
+}
+
+
+/**
+ Create Tds list for Bulk/Interrupt Transfer.
+
+ @param Ohc USB_HC_DEV.
+ @param DevAddr Address of Device.
+ @param EndPoint Endpoint Number.
+ @param PktId Packet Identification of Data Tds.
+ @param Data A pointer to cpu memory address of user data buffer to transfer.
+ @param DataPhy A pointer to pci memory address of user data buffer to transfer.
+ @param DataLen Length of user data to transfer.
+ @param DataToggle Data Toggle Pointer.
+ @param MaxPacket Maximum packet size for Bulk/Interrupt transfer.
+ @param IsLow Is Low Speed Device.
+
+ @return The Tds list head for the bulk transfer.
+
+**/
+OHCI_TD_HW *
+OhciCreateBulkOrIntTds (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DevAddr,
+ IN UINT8 EndPoint,
+ IN UINT8 PktId,
+ IN UINT8 *Data,
+ IN UINT8 *DataPhy,
+ IN UINTN DataLen,
+ IN OUT UINT8 *DataToggle,
+ IN UINT8 MaxPacket,
+ IN BOOLEAN IsLow
+ )
+{
+ OHCI_ED_HW *Ed;
+ OHCI_TD_HW *DataTd;
+ OHCI_TD_HW *FirstDataTd;
+ OHCI_TD_HW *PrevDataTd;
+ UINTN ThisTdLen;
+ UINT8 EP;
+#if 1
+ EP = EndPoint >> 7;
+ DEBUG((EFI_D_INIT, "+++OhciCreateBulkOrIntTds(EP%d : %p)\n", EP, Ohc->EdHw[EP]));
+
+ DataTd = NULL;
+ FirstDataTd = NULL;
+ PrevDataTd = NULL;
+ //
+ // Create data packets for the transfer
+ //
+ while (DataLen > 0) {
+ //
+ // PktSize is the data load size that each Td.
+ //
+ ThisTdLen = DataLen;
+
+ if (DataLen > MaxPacket) {
+ ThisTdLen = MaxPacket;
+ }
+
+ DataTd = OhciCreateDataTd (
+ Ohc,
+ DevAddr,
+ EndPoint,
+ Data,
+ DataPhy,
+ ThisTdLen,
+ PktId,
+ (*DataToggle + 2),
+ IsLow
+ );
+
+ if (DataTd == NULL) {
+ DEBUG((EFI_D_ERROR, "FAIL! OhciCreateDataTd\n"));
+ goto FREE_TD;
+ }
+/*
+ if (PktId == INPUT_PACKET_ID) {
+ DataTd->gtd_info.b.buffer_rounding = 1;
+ }
+*/
+ if (FirstDataTd == NULL) {
+ FirstDataTd = DataTd;
+ FirstDataTd->next_td = NULL;
+ } else {
+ OhciAppendTd (Ohc, PrevDataTd, DataTd);
+ }
+
+ *DataToggle ^= 1;
+ PrevDataTd = DataTd;
+ Data += ThisTdLen;
+ DataPhy += ThisTdLen;
+ DataLen -= ThisTdLen;
+ }
+
+ Ed = Ohc->EdHw[EP];
+ Ed->ed_info.data = 0;
+ Ed->ed_info.b.func_addr = DevAddr;
+ Ed->ed_info.b.ep_num = EP;
+ Ed->ed_info.b.direction = 0; //IN DIRECTION
+ Ed->ed_info.b.speed = IsLow?1:0; // speed
+ Ed->ed_info.b.format = 0; // gTD
+ Ed->ed_info.b.mps = MaxPacket;
+ Ed->tail_td_ptr = 0;
+ Ed->head_td_ptr = FirstDataTd;
+ Ed->next_ed = 0;
+
+ Ohc->LastTd = PrevDataTd;
+
+ DEBUG((EFI_D_INIT, "---OhciCreateBulkOrIntTds()\n"));
+
+ return Ed;
+
+FREE_TD:
+ if (FirstDataTd != NULL) {
+ OhciDestoryTds (Ohc, FirstDataTd);
+ }
+
+ return NULL;
+#else
+ DataTd = NULL;
+ FirstDataTd = NULL;
+ PrevDataTd = NULL;
+
+ //
+ // Create data packets for the transfer
+ //
+ while (DataLen > 0) {
+ //
+ // PktSize is the data load size that each Td.
+ //
+ ThisTdLen = DataLen;
+
+ if (DataLen > MaxPacket) {
+ ThisTdLen = MaxPacket;
+ }
+
+ DataTd = OhciCreateDataTd (
+ Ohc,
+ DevAddr,
+ EndPoint,
+ Data,
+ DataPhy,
+ ThisTdLen,
+ PktId,
+ *DataToggle,
+ IsLow
+ );
+
+ if (DataTd == NULL) {
+ goto FREE_TD;
+ }
+
+ if (PktId == INPUT_PACKET_ID) {
+ DataTd->TdHw.ShortPacket = TRUE;
+ }
+
+ if (FirstDataTd == NULL) {
+ FirstDataTd = DataTd;
+ FirstDataTd->NextTd = NULL;
+ } else {
+ OhciAppendTd (Ohc, PrevDataTd, DataTd);
+ }
+
+ *DataToggle ^= 1;
+ PrevDataTd = DataTd;
+ Data += ThisTdLen;
+ DataPhy += ThisTdLen;
+ DataLen -= ThisTdLen;
+ }
+
+ return FirstDataTd;
+
+FREE_TD:
+ if (FirstDataTd != NULL) {
+ OhciDestoryTds (Ohc, FirstDataTd);
+ }
+#endif
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciQueue.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciQueue.h
new file mode 100644
index 000000000..8c22c95e6
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciQueue.h
@@ -0,0 +1,395 @@
+/** @file
+
+ The definition for OHCI register operation routines.
+
+Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+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 _EFI_OHCI_QUEUE_H_
+#define _EFI_OHCI_QUEUE_H_
+
+#if 1
+//==================================================================
+// data structure
+//
+// <OHCI>
+//
+
+typedef union
+{
+ UINT32 data;
+ struct {
+ // bit[6:0] : function address
+ unsigned func_addr : 7;
+ // bit[10:7] : endpoint number
+ unsigned ep_num : 4;
+ // bit[12:11] : direction
+ unsigned direction : 2;
+ // bit[13] : speed
+ unsigned speed : 1;
+ // bit[14] : skip (1->skip this ED)
+ unsigned skip : 1;
+ // bit[15] : format (0->gTD, 1->isoTD)
+ unsigned format : 1;
+ // bit[26:16] : maximum packet size
+ unsigned mps : 11;
+ // bit[31:27] :
+ unsigned reserved31_27 : 5;
+ }b;
+}ed_info_t;
+
+typedef struct
+{
+ ed_info_t ed_info;
+ UINT32 tail_td_ptr;
+ UINT32 head_td_ptr;
+ UINT32 next_ed;
+} OHCI_ED_HW;
+
+typedef union
+{
+ UINT32 data;
+ struct {
+ // bit[17:0] :
+ unsigned reserved17_0 : 18;
+ // bit[18] : buffer rounding (0->exactly fill the defined buffer, 1->may be smaller than the defined buffer)
+ unsigned buffer_rounding : 1;
+ // bit[20:19] : pid (0->setup, 1->out, 2->in, 3->reserved)
+ unsigned pid : 2;
+ // bit[23:21] : delay interrupt
+ unsigned delay_interrupt : 3;
+ // bit[25:24] : data toggle
+ unsigned data_toggle : 2;
+ // bit[27:26] : error count
+ unsigned error_count : 2;
+ // bit[31:28] : condition code
+ unsigned condition_code : 4;
+ }b;
+}gtd_info_t;
+
+typedef struct
+{
+ gtd_info_t gtd_info;
+ UINT32 current_buf_ptr;
+ UINT32 next_td;
+ UINT32 buffer_end;
+} OHCI_TD_HW;
+
+typedef struct _OHCI_TD_SW OHCI_TD_SW;
+
+struct _OHCI_TD_SW{
+ OHCI_TD_HW *TdHw;
+ OHCI_TD_SW *NextTd;
+ UINT32 *Data;
+ UINT32 DataLen;
+};
+
+struct _OHCI_HCCA {
+#define NUM_INTS 32
+ UINT32 int_table [NUM_INTS]; /* periodic schedule */
+
+ /*
+ * OHCI defines u16 frame_no, followed by u16 zero pad.
+ * Since some processors can't do 16 bit bus accesses,
+ * portable access must be a 32 bits wide.
+ */
+ UINT32 frame_no; /* current frame number */
+ UINT32 done_head; /* info returned for an interrupt */
+ UINT8 reserved_for_hc [116];
+ UINT8 what [4]; /* spec only identifies 252 bytes :) */
+} __attribute__ ((aligned(256)));
+
+typedef struct _OHCI_HCCA OHCI_HCCA;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct {
+ UINT32 HorizonLink;
+ UINT32 VerticalLink;
+} OHCI_QH_HW;
+
+typedef struct _OHCI_QH_SW OHCI_QH_SW;
+
+struct _OHCI_QH_SW {
+ OHCI_QH_HW QhHw;
+ OHCI_QH_SW *NextQh;
+ OHCI_TD_HW *TDs;
+ UINTN Interval;
+};
+#else
+//
+// Macroes used to set various links in OHCI's driver.
+// In this OHCI driver, QH's horizontal link always pointers to other QH,
+// and its vertical link always pointers to TD. TD's next pointer always
+// pointers to other sibling TD. Frame link always pointers to QH because
+// ISO transfer isn't supported.
+//
+// We should use UINT32 to access these pointers to void race conditions
+// with hardware.
+//
+#define QH_HLINK(Pointer, Terminate) \
+ (((UINT32) ((UINTN) (Pointer)) & 0xFFFFFFF0) | 0x02 | ((Terminate) ? 0x01 : 0))
+
+#define QH_VLINK(Pointer, Terminate) \
+ (((UINT32) ((UINTN) (Pointer)) & 0xFFFFFFF0) | ((Terminate) ? 0x01 : 0))
+
+#define TD_LINK(Pointer, VertFirst, Terminate) \
+ (((UINT32) ((UINTN) (Pointer)) & 0xFFFFFFF0) | \
+ ((VertFirst) ? 0x04 : 0) | ((Terminate) ? 0x01 : 0))
+
+#define LINK_TERMINATED(Link) (((Link) & 0x01) != 0)
+
+#define OHCI_ADDR(QhOrTd) ((VOID *) (UINTN) ((QhOrTd) & 0xFFFFFFF0))
+
+#pragma pack(1)
+//
+// Both links in QH has this internal structure:
+// Next pointer: 28, Reserved: 2, NextIsQh: 1, Terminate: 1
+// This is the same as frame list entry.
+//
+typedef struct {
+ UINT32 HorizonLink;
+ UINT32 VerticalLink;
+} OHCI_QH_HW;
+
+//
+// Next link in TD has this internal structure:
+// Next pointer: 28, Reserved: 1, Vertical First: 1, NextIsQh: 1, Terminate: 1
+//
+typedef struct {
+ UINT32 NextLink;
+ UINT32 ActualLen : 11;
+ UINT32 Reserved1 : 5;
+ UINT32 Status : 8;
+ UINT32 IntOnCpl : 1;
+ UINT32 IsIsoch : 1;
+ UINT32 LowSpeed : 1;
+ UINT32 ErrorCount : 2;
+ UINT32 ShortPacket : 1;
+ UINT32 Reserved2 : 2;
+ UINT32 PidCode : 8;
+ UINT32 DeviceAddr : 7;
+ UINT32 EndPoint : 4;
+ UINT32 DataToggle : 1;
+ UINT32 Reserved3 : 1;
+ UINT32 MaxPacketLen: 11;
+ UINT32 DataBuffer;
+} OHCI_TD_HW;
+#pragma pack()
+
+typedef struct _OHCI_TD_SW OHCI_TD_SW;
+typedef struct _OHCI_QH_SW OHCI_QH_SW;
+
+struct _OHCI_QH_SW {
+ OHCI_QH_HW QhHw;
+ OHCI_QH_SW *NextQh;
+ OHCI_TD_SW *TDs;
+ UINTN Interval;
+};
+
+struct _OHCI_TD_SW {
+ OHCI_TD_HW TdHw;
+ OHCI_TD_SW *NextTd;
+ UINT8 *Data;
+ UINT16 DataLen;
+};
+#endif
+
+/**
+ Link the TD To QH.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head for the TD to link to.
+ @param Td The TD to link.
+
+**/
+VOID
+OhciLinkTdToQh (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ED_HW *Ed,
+ IN UINT8 Class
+ );
+
+
+/**
+ Unlink TD from the QH.
+
+ @param Qh The queue head to unlink from.
+ @param Td The TD to unlink.
+
+ @return None.
+
+**/
+VOID
+OhciUnlinkTdFromQh (
+ IN OHCI_QH_SW *Qh,
+ IN OHCI_TD_HW *Td
+ );
+
+/**
+ Map address of request structure buffer.
+
+ @param Ohc The OHCI device.
+ @param Request The user request buffer.
+ @param MappedAddr Mapped address of request.
+ @param Map Identificaion of this mapping to return.
+
+ @return EFI_SUCCESS Success.
+ @return EFI_DEVICE_ERROR Fail to map the user request.
+
+**/
+EFI_STATUS
+OhciMapUserRequest (
+ IN USB_HC_DEV *Ohc,
+ IN OUT VOID *Request,
+ OUT UINT8 **MappedAddr,
+ OUT VOID **Map
+ );
+
+
+/**
+ Map address of user data buffer.
+
+ @param Ohc The OHCI device.
+ @param Direction Direction of the data transfer.
+ @param Data The user data buffer.
+ @param Len Length of the user data.
+ @param PktId Packet identificaion.
+ @param MappedAddr Mapped address to return.
+ @param Map Identificaion of this mapping to return.
+
+ @return EFI_SUCCESS Success.
+ @return EFI_DEVICE_ERROR Fail to map the user data.
+
+**/
+EFI_STATUS
+OhciMapUserData (
+ IN USB_HC_DEV *Ohc,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN VOID *Data,
+ IN OUT UINTN *Len,
+ OUT UINT8 *PktId,
+ OUT UINT8 **MappedAddr,
+ OUT VOID **Map
+ );
+
+
+/**
+ Delete a list of TDs.
+
+ @param Ohc The OHCI device.
+ @param FirstTd TD link list head.
+
+ @return None.
+
+**/
+VOID
+OhciDestoryTds (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_TD_SW *FirstTd
+ );
+
+
+/**
+ Create an initialize a new queue head.
+
+ @param Ohc The OHCI device.
+ @param Interval The polling interval for the queue.
+
+ @return The newly created queue header.
+
+**/
+OHCI_QH_SW *
+OhciCreateQh (
+ IN USB_HC_DEV *Ohc,
+ IN UINTN Interval
+ );
+
+
+/**
+ Create Tds list for Control Transfer.
+
+ @param Ohc The OHCI device.
+ @param DeviceAddr The device address.
+ @param DataPktId Packet Identification of Data Tds.
+ @param Request A pointer to cpu memory address of request structure buffer to transfer.
+ @param RequestPhy A pointer to pci memory address of request structure buffer to transfer.
+ @param Data A pointer to cpu memory address of user data buffer to transfer.
+ @param DataPhy A pointer to pci memory address of user data buffer to transfer.
+ @param DataLen Length of user data to transfer.
+ @param MaxPacket Maximum packet size for control transfer.
+ @param IsLow Full speed or low speed.
+
+ @return The Td list head for the control transfer.
+
+**/
+OHCI_ED_HW *
+OhciCreateCtrlTds (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DeviceAddr,
+ IN UINT8 DataPktId,
+ IN UINT8 *Request,
+ IN UINT8 *RequestPhy,
+ IN UINT8 *Data,
+ IN UINT8 *DataPhy,
+ IN UINTN DataLen,
+ IN UINT8 MaxPacket,
+ IN BOOLEAN IsLow
+ );
+
+
+/**
+ Create Tds list for Bulk/Interrupt Transfer.
+
+ @param Ohc USB_HC_DEV.
+ @param DevAddr Address of Device.
+ @param EndPoint Endpoint Number.
+ @param PktId Packet Identification of Data Tds.
+ @param Data A pointer to cpu memory address of user data buffer to transfer.
+ @param DataPhy A pointer to pci memory address of user data buffer to transfer.
+ @param DataLen Length of user data to transfer.
+ @param DataToggle Data Toggle Pointer.
+ @param MaxPacket Maximum packet size for Bulk/Interrupt transfer.
+ @param IsLow Is Low Speed Device.
+
+ @return The Tds list head for the bulk transfer.
+
+**/
+OHCI_TD_HW *
+OhciCreateBulkOrIntTds (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DevAddr,
+ IN UINT8 EndPoint,
+ IN UINT8 PktId,
+ IN UINT8 *Data,
+ IN UINT8 *DataPhy,
+ IN UINTN DataLen,
+ IN OUT UINT8 *DataToggle,
+ IN UINT8 MaxPacket,
+ IN BOOLEAN IsLow
+ );
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciReg.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciReg.c
new file mode 100644
index 000000000..29879027e
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciReg.c
@@ -0,0 +1,292 @@
+/** @file
+
+ The OHCI register operation routines.
+
+Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
+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 "Ohci.h"
+
+
+/**
+ Read a OHCI register.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Offset Register offset to USB_BAR_INDEX.
+
+ @return Content of register.
+
+**/
+UINT32
+OhciReadReg (
+ IN USB_HC_DEV *Ohc,
+ IN UINT32 Offset
+ )
+{
+ UINT32 Data;
+ EFI_STATUS Status;
+
+ Status = Ohc->PciIo->Mem.Read (
+ Ohc->PciIo,
+ EfiPciIoWidthUint32,
+ OHC_BAR_INDEX,
+ (UINT64) (Offset),
+ 1,
+ &Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "OhcReadOpReg: Pci Io Read error - %r at %d\n", Status, Offset));
+ Data = 0xFFFF;
+ }
+
+ return Data;
+}
+
+
+/**
+ Write data to OHCI register.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Offset Register offset to USB_BAR_INDEX.
+ @param Data Data to write.
+
+**/
+VOID
+OhciWriteReg (
+ IN USB_HC_DEV *Ohc,
+ IN UINT32 Offset,
+ IN UINT32 Data
+ )
+{
+ EFI_STATUS Status;
+
+ Status = Ohc->PciIo->Mem.Write (
+ Ohc->PciIo,
+ EfiPciIoWidthUint32,
+ OHC_BAR_INDEX,
+ (UINT64) (Offset),
+ 1,
+ &Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "OhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));
+ }
+}
+
+
+/**
+ Set a bit of the OHCI Register.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Offset Register offset to USB_BAR_INDEX.
+ @param Bit The bit to set.
+
+**/
+VOID
+OhciSetRegBit (
+ IN USB_HC_DEV *Ohc,
+ IN UINT32 Offset,
+ IN UINT16 Bit
+ )
+{
+ UINT16 Data;
+
+ Data = OhciReadReg (Ohc, Offset);
+ Data = (UINT16) (Data |Bit);
+ OhciWriteReg (Ohc, Offset, Data);
+}
+
+
+/**
+ Clear a bit of the OHCI Register.
+
+ @param PciIo The PCI_IO protocol to access the PCI.
+ @param Offset Register offset to USB_BAR_INDEX.
+ @param Bit The bit to clear.
+
+**/
+VOID
+OhciClearRegBit (
+ IN USB_HC_DEV *Ohc,
+ IN UINT32 Offset,
+ IN UINT16 Bit
+ )
+{
+ UINT16 Data;
+
+ Data = OhciReadReg (Ohc, Offset);
+ Data = (UINT16) (Data & ~Bit);
+ OhciWriteReg (Ohc, Offset, Data);
+}
+
+
+/**
+ Clear all the interrutp status bits, these bits
+ are Write-Clean.
+
+ @param Ohc The OHCI device.
+
+**/
+VOID
+OhciAckAllInterrupt (
+ IN USB_HC_DEV *Ohc
+ )
+{
+ //OhciWriteReg (Ohc, USBSTS_OFFSET, 0x3F);
+
+ //
+ // If current HC is halted, re-enable it. Host Controller Process Error
+ // is a temporary error status.
+ //
+ if (!OhciIsHcWorking (Ohc)) {
+ DEBUG ((EFI_D_ERROR, "OhciAckAllInterrupt: re-enable the OHCI from system error\n"));
+ Ohc->Usb2Hc.SetState (&Ohc->Usb2Hc, EfiUsbHcStateOperational);
+ }
+}
+
+
+/**
+ Stop the host controller.
+
+ @param Ohc The OHCI device.
+ @param Timeout Max time allowed.
+
+ @retval EFI_SUCCESS The host controller is stopped.
+ @retval EFI_TIMEOUT Failed to stop the host controller.
+
+**/
+EFI_STATUS
+OhciStopHc (
+ IN USB_HC_DEV *Ohc,
+ IN UINTN Timeout
+ )
+{
+#if 1
+/*
+ UINT32 UsbCtr;
+ UsbCtr = OhciReadReg(Ohc, HC_CONTROL_OFFSET);
+ UsbCtr &= (1<<9); //all except of RWC is clear
+ OhciWriteReg(Ohc, HC_CONTROL_OFFSET, UsbCtr);
+*/
+ return EFI_SUCCESS;
+#else
+ UINT16 UsbSts;
+ UINTN Index;
+ OhciClearRegBit (Ohc, USBCMD_OFFSET, USBCMD_RS);
+
+ //
+ // ensure the HC is in halt status after send the stop command
+ // Timeout is in us unit.
+ //
+ for (Index = 0; Index < (Timeout / 50) + 1; Index++) {
+ UsbSts = OhciReadReg (Ohc, USBSTS_OFFSET);
+
+ if ((UsbSts & USBSTS_HCH) == USBSTS_HCH) {
+ return EFI_SUCCESS;
+ }
+
+ gBS->Stall (50);
+ }
+
+ return EFI_TIMEOUT;
+#endif
+}
+
+
+/**
+ Check whether the host controller operates well.
+
+ @param PciIo The PCI_IO protocol to use.
+
+ @retval TRUE Host controller is working.
+ @retval FALSE Host controller is halted or system error.
+
+**/
+BOOLEAN
+OhciIsHcWorking (
+ IN USB_HC_DEV *Ohc
+ )
+{
+ UINT16 UsbSts;
+ /*
+ UsbSts = OhciReadReg (Ohc, USBSTS_OFFSET);
+
+ if ((UsbSts & (USBSTS_HCPE | USBSTS_HSE | USBSTS_HCH)) != 0) {
+ DEBUG ((EFI_D_ERROR, "OhciIsHcWorking: current USB state is %x\n", UsbSts));
+ return FALSE;
+ }
+ */
+ return TRUE;
+}
+
+
+/**
+ Set the OHCI frame list base address. It can't use
+ OhciWriteReg which access memory in UINT16.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Addr Address to set.
+
+**/
+/*
+VOID
+OhciSetFrameListBaseAddr (
+ IN USB_HC_DEV *Ohc,
+ IN VOID *Addr
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Data;
+
+ Data = (UINT32) ((UINTN) Addr & 0xFFFFF000);
+
+ Status = PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ USB_BAR_INDEX,
+ (UINT64) USB_FRAME_BASE_OFFSET,
+ 1,
+ &Data
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "OhciSetFrameListBaseAddr: PciIo Io.Write error: %r\n", Status));
+ }
+}
+*/
+
+/**
+ Disable USB Emulation.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL protocol to use.
+
+**/
+
+/*
+VOID
+OhciTurnOffUsbEmulation (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+{
+ UINT16 Command;
+
+ Command = 0;
+
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_EMULATION_OFFSET,
+ 1,
+ &Command
+ );
+}*/
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciReg.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciReg.h
new file mode 100644
index 000000000..729720e98
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciReg.h
@@ -0,0 +1,286 @@
+/** @file
+
+ The definition for OHCI register operation routines.
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+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 _EFI_OHCI_REG_H_
+#define _EFI_OHCI_REG_H_
+
+//
+// OHCI register offset
+//
+
+#define OHCI_FRAME_NUM 1024
+
+//
+// Register offset and PCI related staff
+//
+#define USB_BAR_INDEX 4
+
+#define USBCMD_OFFSET 0
+#define USBSTS_OFFSET 2
+#define USBINTR_OFFSET 4
+//#define HC_PORT_STATUS_OFFSET 0x10
+#define USB_FRAME_NO_OFFSET 6
+#define USB_FRAME_BASE_OFFSET 8
+#define USB_EMULATION_OFFSET 0xC0
+
+// Register offset for OHCI
+#define INC4(a) ((a)+4)
+#define HC_REVISION_OFFSET 0x0
+#define HC_CONTROL_OFFSET INC4(HC_REVISION_OFFSET)
+#define HC_COM_STATUS_OFFSET INC4(HC_CONTROL_OFFSET)
+#define HC_INT_STATUS_OFFSET INC4(HC_COM_STATUS_OFFSET)
+#define HC_INT_ENABLE_OFFSET INC4(HC_INT_STATUS_OFFSET)
+#define HC_INT_DISABLE_OFFSET INC4(HC_INT_ENABLE_OFFSET)
+#define HC_HCCA_OFFSET INC4(HC_INT_DISABLE_OFFSET)
+#define HC_PERIOD_CUTTENTED_OFFSET INC4(HC_HCCA_OFFSET)
+
+
+#define HC_PRID_HEADED_OFFSET 0x40
+#define HC_PRID_CURRED_OFFSET 0x1C
+#define HC_CTRL_HEADED_OFFSET 0x20
+#define HC_CTRL_CURRED_OFFSET 0x24
+#define HC_BULK_HEADED_OFFSET 0x28
+#define HC_BULK_CURRED_OFFSET 0x2C
+
+#define HC_FMINTERVAL_OFFSET 0x34
+#define HC_RH_DESCRIPTORA_OFFSET 0x48
+#define HC_RH_DESCRIPTORB_OFFSET 0x4C
+#define HC_RH_STATUS_OFFSET 0x50
+#define HC_PORT_STATUS_OFFSET 0x54
+
+
+#define HC_CLASS_CONTROL 0
+#define HC_CLASS_INTERRUPT 1
+
+//
+// Packet IDs
+//
+#define SETUP_PACKET_ID 0x0
+#define OUTPUT_PACKET_ID 0x1
+#define INPUT_PACKET_ID 0x2
+#define ERROR_PACKET_ID 0x3
+
+//
+// USB port status and control bit definition.
+//
+#define USBPORTSC_CCS BIT0 // Current Connect Status
+#define USBPORTSC_PED BIT1 // Port Enable / Disable
+#define USBPORTSC_SUSP BIT2 // Suspend
+#define USBPORTSC_POCI BIT3 // OVER CURRNET INDICATOR
+#define USBPORTSC_PR BIT4 // Port Reset
+
+#define USBPORTSC_PPS BIT8 // Port Power
+#define USBPORTSC_LSDA BIT9 // Low Speed Device Attached
+
+#define USBPORTSC_CSC BIT16 // Connect Status Change
+#define USBPORTSC_PEDC BIT17 // Enable Change
+#define USBPORTSC_PSSC BIT18 // Suspend Change
+#define USBPORTSC_OCIC BIT19 // Over Currnet Change
+#define USBPORTSC_PRSC BIT20 // Reset Change
+
+
+
+
+
+//
+// OHCI Spec said it must implement 2 ports each host at least,
+// and if more, check whether the bit7 of PORTSC is always 1.
+// So here assume the max of port number each host is 16.
+//
+#define USB_MAX_ROOTHUB_PORT 0x0F
+
+//
+// Command register bit definitions
+//
+#define USBCMD_RS BIT0 // Run/Stop
+#define USBCMD_HCRESET BIT1 // Host reset
+#define USBCMD_GRESET BIT2 // Global reset
+#define USBCMD_EGSM BIT3 // Global Suspend Mode
+#define USBCMD_FGR BIT4 // Force Global Resume
+#define USBCMD_SWDBG BIT5 // SW Debug mode
+#define USBCMD_CF BIT6 // Config Flag (sw only)
+#define USBCMD_MAXP BIT7 // Max Packet (0 = 32, 1 = 64)
+
+//
+// USB Status register bit definitions
+//
+#define USBSTS_USBINT BIT0 // Interrupt due to IOC
+#define USBSTS_ERROR BIT1 // Interrupt due to error
+#define USBSTS_RD BIT2 // Resume Detect
+#define USBSTS_HSE BIT3 // Host System Error
+#define USBSTS_HCPE BIT4 // Host Controller Process Error
+#define USBSTS_HCH BIT5 // HC Halted
+
+#define USBTD_ACTIVE BIT7 // TD is still active
+#define USBTD_STALLED BIT6 // TD is stalled
+#define USBTD_BUFFERR BIT5 // Buffer underflow or overflow
+#define USBTD_BABBLE BIT4 // Babble condition
+#define USBTD_NAK BIT3 // NAK is received
+#define USBTD_CRC BIT2 // CRC/Time out error
+#define USBTD_BITSTUFF BIT1 // Bit stuff error
+
+#define OHC_BAR_INDEX 0 // how many bytes away from USB_BASE to 0x10
+
+/**
+ Read a OHCI register.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Offset Register offset to USB_BAR_INDEX.
+
+ @return Content of register.
+
+**/
+UINT32
+OhciReadReg (
+ IN USB_HC_DEV *Ohc,
+ IN UINT32 Offset
+ );
+
+
+
+/**
+ Write data to OHCI register.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Offset Register offset to USB_BAR_INDEX.
+ @param Data Data to write.
+
+ @return None.
+
+**/
+VOID
+OhciWriteReg (
+ IN USB_HC_DEV *Ohc,
+ IN UINT32 Offset,
+ IN UINT32 Data
+ );
+
+
+
+/**
+ Set a bit of the OHCI Register.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Offset Register offset to USB_BAR_INDEX.
+ @param Bit The bit to set.
+
+ @return None.
+
+**/
+VOID
+OhciSetRegBit (
+ IN USB_HC_DEV *Ohc,
+ IN UINT32 Offset,
+ IN UINT16 Bit
+ );
+
+
+
+/**
+ Clear a bit of the OHCI Register.
+
+ @param PciIo The PCI_IO protocol to access the PCI.
+ @param Offset Register offset to USB_BAR_INDEX.
+ @param Bit The bit to clear.
+
+ @return None.
+
+**/
+VOID
+OhciClearRegBit (
+ IN USB_HC_DEV *Ohc,
+ IN UINT32 Offset,
+ IN UINT16 Bit
+ );
+
+
+/**
+ Clear all the interrutp status bits, these bits
+ are Write-Clean.
+
+ @param Ohc The OHCI device.
+
+ @return None.
+
+**/
+VOID
+OhciAckAllInterrupt (
+ IN USB_HC_DEV *Ohc
+ );
+
+
+/**
+ Stop the host controller.
+
+ @param Ohc The OHCI device.
+ @param Timeout Max time allowed.
+
+ @retval EFI_SUCCESS The host controller is stopped.
+ @retval EFI_TIMEOUT Failed to stop the host controller.
+
+**/
+EFI_STATUS
+OhciStopHc (
+ IN USB_HC_DEV *Ohc,
+ IN UINTN Timeout
+ );
+
+
+
+/**
+ Check whether the host controller operates well.
+
+ @param PciIo The PCI_IO protocol to use.
+
+ @retval TRUE Host controller is working.
+ @retval FALSE Host controller is halted or system error.
+
+**/
+BOOLEAN
+OhciIsHcWorking (
+ IN USB_HC_DEV *Ohc
+ );
+
+
+/**
+ Set the OHCI frame list base address. It can't use
+ OhciWriteReg which access memory in UINT16.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL to use.
+ @param Addr Address to set.
+
+ @return None.
+
+**/
+VOID
+OhciSetFrameListBaseAddr (
+ IN USB_HC_DEV *Ohc,
+ IN VOID *Addr
+ );
+
+
+/**
+ Disable USB Emulation.
+
+ @param PciIo The EFI_PCI_IO_PROTOCOL protocol to use.
+
+ @return None.
+
+**/
+VOID
+OhciTurnOffUsbEmulation (
+ IN USB_HC_DEV *Ohc
+ );
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciSched.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciSched.c
new file mode 100644
index 000000000..a8f99a3d4
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciSched.c
@@ -0,0 +1,1254 @@
+/** @file
+
+ The EHCI register operation routines.
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "Ohci.h"
+
+
+/**
+ Create Frame List Structure.
+
+ @param Ohc OHCI device.
+
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
+ @retval EFI_UNSUPPORTED Map memory fail.
+ @retval EFI_SUCCESS Success.
+
+**/
+EFI_STATUS
+OhciInitFrameList (
+ IN USB_HC_DEV *Ohc
+ )
+{
+ EFI_PHYSICAL_ADDRESS MappedAddr;
+ EFI_STATUS Status;
+ VOID *Buffer;
+ VOID *Mapping;
+ UINTN Pages;
+ UINTN Bytes;
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+
+ DEBUG((EFI_D_INIT, "+++OhciInitFrameList()\n"));
+
+ //
+ // The Frame List is a common buffer that will be
+ // accessed by both the cpu and the usb bus master
+ // at the same time. The Frame List ocupies 4K bytes,
+ // and must be aligned on 4-Kbyte boundaries.
+ //
+ Bytes = 4096;
+ Pages = EFI_SIZE_TO_PAGES (Bytes);
+
+ Status = Ohc->PciIo->AllocateBuffer (
+ Ohc->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ Pages,
+ &Buffer,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "FAIL! AllocateBuffer\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Ohc->PciIo->Map (
+ Ohc->PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ Buffer,
+ &Bytes,
+ &MappedAddr,
+ &Mapping
+ );
+
+#if 1
+ if (EFI_ERROR (Status) || (Bytes != 4096)) {
+ DEBUG((EFI_D_ERROR, "FAIL! Map\n"));
+ Status = EFI_UNSUPPORTED;
+ return Status;
+ }
+
+ Ohc->Hcca = (UINT32 *) (UINTN) Buffer;
+ Ohc->HccaMapping = Mapping;
+
+ OhciWriteReg(Ohc, HC_HCCA_OFFSET, (UINT32)Buffer);
+
+ return EFI_SUCCESS;
+
+#else
+ if (EFI_ERROR (Status) || (Bytes != 4096)) {
+ DEBUG((EFI_D_ERROR, "FAIL! Map\n"));
+ Status = EFI_UNSUPPORTED;
+ goto ON_ERROR;
+ }
+
+
+ Ohc->FrameBase = (UINT32 *) (UINTN) Buffer;
+ Ohc->FrameMapping = Mapping;
+
+ //
+ // Tell the Host Controller where the Frame List lies,
+ // by set the Frame List Base Address Register.
+ //
+ //OhciSetFrameListBaseAddr (Ohc->PciIo, (VOID *) (UINTN) MappedAddr);
+
+ //
+ // Allocate the QH used by sync interrupt/control/bulk transfer.
+ // FS ctrl/bulk queue head is set to loopback so additional BW
+ // can be reclaimed. Notice, LS don't support bulk transfer and
+ // also doesn't support BW reclamation.
+ //
+ Ohc->SyncIntQh = OhciCreateQh (Ohc, 1);
+ Ohc->CtrlQh = OhciCreateQh (Ohc, 1);
+ Ohc->BulkQh = OhciCreateQh (Ohc, 1);
+
+ if ((Ohc->SyncIntQh == NULL) || (Ohc->CtrlQh == NULL) || (Ohc->BulkQh == NULL)) {
+ Ohc->PciIo->Unmap (Ohc->PciIo, Mapping);
+ DEBUG((EFI_D_ERROR, "FAIL! NULL1\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ //
+ // +-------------+
+ // | |
+ // Link the three together: SyncIntQh->CtrlQh->BulkQh <---------+
+ // Each frame entry is linked to this sequence of QH. These QH
+ // will remain on the schedul, never got removed
+ //
+ PhyAddr = UsbHcGetPciAddressForHostMem (Ohc->MemPool, Ohc->CtrlQh, sizeof (OHCI_QH_HW));
+ Ohc->SyncIntQh->QhHw.HorizonLink = QH_HLINK (PhyAddr, FALSE);
+ Ohc->SyncIntQh->NextQh = Ohc->CtrlQh;
+
+ PhyAddr = UsbHcGetPciAddressForHostMem (Ohc->MemPool, Ohc->BulkQh, sizeof (OHCI_QH_HW));
+ Ohc->CtrlQh->QhHw.HorizonLink = QH_HLINK (PhyAddr, FALSE);
+ Ohc->CtrlQh->NextQh = Ohc->BulkQh;
+
+ //
+ // Some old platform such as Intel's Tiger 4 has a difficult time
+ // in supporting the full speed bandwidth reclamation in the previous
+ // mentioned form. Most new platforms don't suffer it.
+ //
+ Ohc->BulkQh->QhHw.HorizonLink = QH_HLINK (PhyAddr, FALSE);
+
+ Ohc->BulkQh->NextQh = NULL;
+
+ Ohc->FrameBaseHostAddr = AllocateZeroPool (4096);
+ if (Ohc->FrameBaseHostAddr == NULL) {
+ DEBUG((EFI_D_ERROR, "FAIL! NULL2\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ PhyAddr = UsbHcGetPciAddressForHostMem (Ohc->MemPool, Ohc->SyncIntQh, sizeof (OHCI_QH_HW));
+ for (Index = 0; Index < OHCI_FRAME_NUM; Index++) {
+ Ohc->FrameBase[Index] = QH_HLINK (PhyAddr, FALSE);
+ Ohc->FrameBaseHostAddr[Index] = (UINT32)(UINTN)Ohc->SyncIntQh;
+ }
+
+ DEBUG((EFI_D_INIT, "---OhciInitFrameList()\n"));
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ if (Ohc->SyncIntQh != NULL) {
+ UsbHcFreeMem (Ohc->MemPool, Ohc->SyncIntQh, sizeof (OHCI_QH_SW));
+ }
+
+ if (Ohc->CtrlQh != NULL) {
+ UsbHcFreeMem (Ohc->MemPool, Ohc->CtrlQh, sizeof (OHCI_QH_SW));
+ }
+
+ if (Ohc->BulkQh != NULL) {
+ UsbHcFreeMem (Ohc->MemPool, Ohc->BulkQh, sizeof (OHCI_QH_SW));
+ }
+
+ Ohc->PciIo->FreeBuffer (Ohc->PciIo, Pages, Buffer);
+ return Status;
+#endif
+}
+
+
+/**
+ Destory FrameList buffer.
+
+ @param Ohc The OHCI device.
+
+**/
+VOID
+OhciDestoryFrameList (
+ IN USB_HC_DEV *Ohc
+ )
+{
+ //
+ // Unmap the common buffer for framelist entry,
+ // and free the common buffer.
+ // Ohci's frame list occupy 4k memory.
+ //
+ DEBUG((EFI_D_INIT, "+++OhciDestoryFrameList()\n"));
+
+#if 1
+#else
+ Ohc->PciIo->Unmap (Ohc->PciIo, Ohc->FrameMapping);
+
+ Ohc->PciIo->FreeBuffer (
+ Ohc->PciIo,
+ EFI_SIZE_TO_PAGES (4096),
+ (VOID *) Ohc->FrameBase
+ );
+
+ if (Ohc->FrameBaseHostAddr != NULL) {
+ FreePool (Ohc->FrameBaseHostAddr);
+ }
+
+ if (Ohc->SyncIntQh != NULL) {
+ UsbHcFreeMem (Ohc->MemPool, Ohc->SyncIntQh, sizeof (OHCI_QH_SW));
+ }
+
+ if (Ohc->CtrlQh != NULL) {
+ UsbHcFreeMem (Ohc->MemPool, Ohc->CtrlQh, sizeof (OHCI_QH_SW));
+ }
+
+ if (Ohc->BulkQh != NULL) {
+ UsbHcFreeMem (Ohc->MemPool, Ohc->BulkQh, sizeof (OHCI_QH_SW));
+ }
+
+ Ohc->FrameBase = NULL;
+ Ohc->FrameBaseHostAddr = NULL;
+ Ohc->SyncIntQh = NULL;
+ Ohc->CtrlQh = NULL;
+ Ohc->BulkQh = NULL;
+#endif
+ DEBUG((EFI_D_INIT, "---OhciDestoryFrameList()\n"));
+}
+
+
+/**
+ Convert the poll rate to the maxium 2^n that is smaller
+ than Interval.
+
+ @param Interval The poll rate to convert.
+
+ @return The converted poll rate.
+
+**/
+UINTN
+OhciConvertPollRate (
+ IN UINTN Interval
+ )
+{
+ UINTN BitCount;
+
+ ASSERT (Interval != 0);
+
+ //
+ // Find the index (1 based) of the highest non-zero bit
+ //
+ BitCount = 0;
+
+ while (Interval != 0) {
+ Interval >>= 1;
+ BitCount++;
+ }
+
+ return (UINTN)1 << (BitCount - 1);
+}
+
+
+/**
+ Link a queue head (for asynchronous interrupt transfer) to
+ the frame list.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head to link into.
+
+**/
+VOID
+OhciLinkQhToFrameList (
+ USB_HC_DEV *Ohc,
+ OHCI_QH_SW *Qh
+ )
+{
+ UINTN Index;
+ OHCI_QH_SW *Prev;
+ OHCI_QH_SW *Next;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ EFI_PHYSICAL_ADDRESS QhPciAddr;
+
+#if 1
+#else
+ ASSERT ((Ohc->FrameBase != NULL) && (Qh != NULL));
+
+ QhPciAddr = UsbHcGetPciAddressForHostMem (Ohc->MemPool, Qh, sizeof (OHCI_QH_HW));
+
+ for (Index = 0; Index < OHCI_FRAME_NUM; Index += Qh->Interval) {
+ //
+ // First QH can't be NULL because we always keep static queue
+ // heads on the frame list
+ //
+ ASSERT (!LINK_TERMINATED (Ohc->FrameBase[Index]));
+ Next = (OHCI_QH_SW*)(UINTN)Ohc->FrameBaseHostAddr[Index];
+ Prev = NULL;
+
+ //
+ // Now, insert the queue head (Qh) into this frame:
+ // 1. Find a queue head with the same poll interval, just insert
+ // Qh after this queue head, then we are done.
+ //
+ // 2. Find the position to insert the queue head into:
+ // Previous head's interval is bigger than Qh's
+ // Next head's interval is less than Qh's
+ // Then, insert the Qh between then
+ //
+ // This method is very much the same as that used by EHCI.
+ // Because each QH's interval is round down to 2^n, poll
+ // rate is correct.
+ //
+ while (Next->Interval > Qh->Interval) {
+ Prev = Next;
+ Next = Next->NextQh;
+ ASSERT (Next != NULL);
+ }
+
+ //
+ // The entry may have been linked into the frame by early insertation.
+ // For example: if insert a Qh with Qh.Interval == 4, and there is a Qh
+ // with Qh.Interval == 8 on the frame. If so, we are done with this frame.
+ // It isn't necessary to compare all the QH with the same interval to
+ // Qh. This is because if there is other QH with the same interval, Qh
+ // should has been inserted after that at FrameBase[0] and at FrameBase[0] it is
+ // impossible (Next == Qh)
+ //
+ if (Next == Qh) {
+ continue;
+ }
+
+ if (Next->Interval == Qh->Interval) {
+ //
+ // If there is a QH with the same interval, it locates at
+ // FrameBase[0], and we can simply insert it after this QH. We
+ // are all done.
+ //
+ ASSERT ((Index == 0) && (Qh->NextQh == NULL));
+
+ Prev = Next;
+ Next = Next->NextQh;
+
+ Qh->NextQh = Next;
+ Prev->NextQh = Qh;
+
+ Qh->QhHw.HorizonLink = Prev->QhHw.HorizonLink;
+
+ Prev->QhHw.HorizonLink = QH_HLINK (QhPciAddr, FALSE);
+ break;
+ }
+
+ //
+ // OK, find the right position, insert it in. If Qh's next
+ // link has already been set, it is in position. This is
+ // guarranted by 2^n polling interval.
+ //
+ if (Qh->NextQh == NULL) {
+ Qh->NextQh = Next;
+ PhyAddr = UsbHcGetPciAddressForHostMem (Ohc->MemPool, Next, sizeof (OHCI_QH_HW));
+ Qh->QhHw.HorizonLink = QH_HLINK (PhyAddr, FALSE);
+ }
+
+ if (Prev == NULL) {
+ Ohc->FrameBase[Index] = QH_HLINK (QhPciAddr, FALSE);
+ Ohc->FrameBaseHostAddr[Index] = (UINT32)(UINTN)Qh;
+ } else {
+ Prev->NextQh = Qh;
+ Prev->QhHw.HorizonLink = QH_HLINK (QhPciAddr, FALSE);
+ }
+ }
+#endif
+}
+
+
+/**
+ Unlink QH from the frame list is easier: find all
+ the precedence node, and pointer there next to QhSw's
+ next.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head to unlink.
+
+**/
+VOID
+OhciUnlinkQhFromFrameList (
+ USB_HC_DEV *Ohc,
+ OHCI_QH_SW *Qh
+ )
+{
+ UINTN Index;
+ OHCI_QH_SW *Prev;
+ OHCI_QH_SW *This;
+#if 1
+#else
+ ASSERT ((Ohc->FrameBase != NULL) && (Qh != NULL));
+
+ for (Index = 0; Index < OHCI_FRAME_NUM; Index += Qh->Interval) {
+ //
+ // Frame link can't be NULL because we always keep static
+ // queue heads on the frame list
+ //
+ ASSERT (!LINK_TERMINATED (Ohc->FrameBase[Index]));
+ This = (OHCI_QH_SW*)(UINTN)Ohc->FrameBaseHostAddr[Index];
+ Prev = NULL;
+
+ //
+ // Walk through the frame's QH list to find the
+ // queue head to remove
+ //
+ while ((This != NULL) && (This != Qh)) {
+ Prev = This;
+ This = This->NextQh;
+ }
+
+ //
+ // Qh may have already been unlinked from this frame
+ // by early action.
+ //
+ if (This == NULL) {
+ continue;
+ }
+
+ if (Prev == NULL) {
+ //
+ // Qh is the first entry in the frame
+ //
+ Ohc->FrameBase[Index] = Qh->QhHw.HorizonLink;
+ Ohc->FrameBaseHostAddr[Index] = (UINT32)(UINTN)Qh->NextQh;
+ } else {
+ Prev->NextQh = Qh->NextQh;
+ Prev->QhHw.HorizonLink = Qh->QhHw.HorizonLink;
+ }
+ }
+#endif
+}
+
+
+/**
+ Check TDs Results.
+
+ @param Ohc This OHCI device.
+ @param Td OHCI_TD_HW to check.
+ @param IsLow Is Low Speed Device.
+ @param QhResult Return the result of this TD list.
+
+ @return Whether the TD's result is finialized.
+
+**/
+BOOLEAN
+OhciCheckTdStatus (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ED_HW *Ed,
+ IN BOOLEAN IsLow,
+ OUT OHCI_QH_RESULT *QhResult,
+ IN UINT8 Class
+ )
+{
+ UINTN Len;
+ UINT8 State;
+ BOOLEAN Finished;
+ OHCI_TD_SW *CurTdSw;
+ OHCI_TD_HW *TdHw;
+
+ Finished = TRUE;
+
+ if(Class == HC_CLASS_CONTROL)
+ CurTdSw = Ohc->CtrlQh;
+ else // HC_CLASS_INTERRUPT
+ CurTdSw = Ohc->IntrQh;
+
+ TdHw = CurTdSw->TdHw;
+ //
+ // Initialize the data toggle to that of the first
+ // TD. The next toggle to use is either:
+ // 1. first TD's toggle if no TD is executed OK
+ // 2. the next toggle of last executed-OK TD
+ //
+ QhResult->Result = EFI_USB_NOERROR;
+ QhResult->NextToggle = (UINT8)(TdHw->gtd_info.b.data_toggle & 1);
+ QhResult->Complete = 0;
+
+#if 1
+ if(Class == HC_CLASS_CONTROL)
+ {
+ while(Ohc->Hcca->done_head != Ohc->LastTd)
+ {
+ DEBUG((EFI_D_ERROR, ".\n"));
+ OhciWriteReg(Ohc, HC_INT_STATUS_OFFSET, 0x2);
+ }
+ }
+ else
+ {
+ OhciWriteReg(Ohc, HC_INT_STATUS_OFFSET, 0x2);
+ if(Ohc->Hcca->done_head != Ohc->LastTd)
+ {
+ Finished = FALSE;
+ QhResult->Complete = 0;
+ return Finished;
+ }
+ }
+
+ Ohc->Hcca->done_head = NULL;
+ DEBUG((EFI_D_ERROR, ">\n"));
+
+ while (TdHw != NULL) {
+ if(TdHw->current_buf_ptr == NULL)
+ {
+ if(TdHw->gtd_info.b.error_count != 0)
+ {
+ QhResult->Result |= EFI_USB_ERR_NOTEXECUTE;
+ DEBUG((EFI_D_ERROR, "FAIL! EXECUTE ERROR1\n"));
+ Finished = TRUE;
+ OhciDumpSWTds(Ohc->CtrlQh);
+ OhcDumpRegs(Ohc);
+ goto ON_EXIT;
+ }
+
+ if(TdHw->gtd_info.b.condition_code != 0)
+ {
+ switch(TdHw->gtd_info.b.condition_code)
+ {
+ case 4: //stall
+ QhResult->Result |= EFI_USB_ERR_STALL;
+ DEBUG((EFI_D_ERROR, "FAIL! EFI_USB_ERR_STALL\n"));
+ break;
+ default :
+ QhResult->Result |= EFI_USB_ERR_NOTEXECUTE;
+ DEBUG((EFI_D_ERROR, "FAIL! EXECUTE ERROR2\n"));
+ break;
+ }
+
+ Finished = TRUE;
+ OhciDumpSWTds(Ohc->CtrlQh);
+ OhcDumpRegs(Ohc);
+ goto ON_EXIT;
+ }
+
+ QhResult->NextToggle = (TdHw->gtd_info.b.data_toggle & 1) ? 0 : 1;
+ //
+ // This TD is finished OK or met short packet read. Update the
+ // transfer length if it isn't a SETUP.
+ //
+
+ if (TdHw->gtd_info.b.pid != SETUP_PACKET_ID) {
+ QhResult->Complete += CurTdSw->DataLen;
+ }
+
+ //
+ // Short packet condition for full speed input TD, also
+ // terminate the transfer
+ //
+ /*
+ if (!IsLow && (TdHw->ShortPacket == 1) && (Len < Td->DataLen)) {
+ DEBUG ((EFI_D_INFO, "OhciCheckTdStatus: short packet read occured\n"));
+
+ Finished = TRUE;
+ goto ON_EXIT;
+ }*/
+ } // if(TdHw->current_buf_ptr == NULL)
+ /*else
+ {
+ QhResult->Result |= EFI_USB_ERR_NOTEXECUTE;
+ DEBUG((EFI_D_ERROR, "FAIL! EXECUTE ERROR3\n"));
+ Finished = TRUE;
+ goto ON_EXIT;
+ }*/
+ CurTdSw = CurTdSw->NextTd;
+ TdHw = CurTdSw->TdHw;
+ }
+
+ if(!Finished)
+ {
+ OhciDumpSWTds(Ohc->CtrlQh);
+ OhcDumpRegs(Ohc);
+ }
+#else
+ while (Td != NULL) {
+ TdHw = &Td->TdHw;
+ State = (UINT8)TdHw->Status;
+
+ //
+ // OHCI will set STALLED bit when it abort the execution
+ // of TD list. There are several reasons:
+ // 1. BABBLE error happened
+ // 2. Received a STALL response
+ // 3. Error count decreased to zero.
+ //
+ // It also set CRC/Timeout/NAK/Buffer Error/BitStuff Error
+ // bits when corresponding conditions happen. But these
+ // conditions are not deadly, that is a TD can successfully
+ // completes even these bits are set. But it is likely that
+ // upper layer won't distinguish these condtions. So, only
+ // set these bits when TD is actually halted.
+ //
+ if ((State & USBTD_STALLED) != 0) {
+ if ((State & USBTD_BABBLE) != 0) {
+ QhResult->Result |= EFI_USB_ERR_BABBLE;
+
+ } else if (TdHw->ErrorCount != 0) {
+ QhResult->Result |= EFI_USB_ERR_STALL;
+ }
+
+ if ((State & USBTD_CRC) != 0) {
+ QhResult->Result |= EFI_USB_ERR_CRC;
+ }
+
+ if ((State & USBTD_BUFFERR) != 0) {
+ QhResult->Result |= EFI_USB_ERR_BUFFER;
+ }
+
+ if ((Td->TdHw.Status & USBTD_BITSTUFF) != 0) {
+ QhResult->Result |= EFI_USB_ERR_BITSTUFF;
+ }
+
+ if (TdHw->ErrorCount == 0) {
+ QhResult->Result |= EFI_USB_ERR_TIMEOUT;
+ }
+
+ Finished = TRUE;
+ goto ON_EXIT;
+
+ } else if ((State & USBTD_ACTIVE) != 0) {
+ //
+ // The TD is still active, no need to check further.
+ //
+ QhResult->Result |= EFI_USB_ERR_NOTEXECUTE;
+
+ Finished = FALSE;
+ goto ON_EXIT;
+
+ } else {
+ //
+ // Update the next data toggle, it is always the
+ // next to the last known-good TD's data toggle if
+ // any TD is executed OK
+ //
+ QhResult->NextToggle = (UINT8) (1 - (UINT8)TdHw->DataToggle);
+
+ //
+ // This TD is finished OK or met short packet read. Update the
+ // transfer length if it isn't a SETUP.
+ //
+ Len = (TdHw->ActualLen + 1) & 0x7FF;
+
+ if (TdHw->PidCode != SETUP_PACKET_ID) {
+ QhResult->Complete += Len;
+ }
+
+ //
+ // Short packet condition for full speed input TD, also
+ // terminate the transfer
+ //
+ if (!IsLow && (TdHw->ShortPacket == 1) && (Len < Td->DataLen)) {
+ DEBUG ((EFI_D_INFO, "OhciCheckTdStatus: short packet read occured\n"));
+
+ Finished = TRUE;
+ goto ON_EXIT;
+ }
+ }
+
+ Td = Td->NextTd;
+ }
+#endif
+
+ON_EXIT:
+ //
+ // Check whether HC is halted. Don't move this up. It must be
+ // called after data toggle is successfully updated.
+ //
+ if (!OhciIsHcWorking (Ohc->PciIo)) {
+ QhResult->Result |= EFI_USB_ERR_SYSTEM;
+ Finished = TRUE;
+ }
+
+ if (Finished) {
+ Ohc->PciIo->Flush (Ohc->PciIo);
+ }
+
+ OhciAckAllInterrupt (Ohc);
+ return Finished;
+}
+
+
+/**
+ Check the result of the transfer.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head of the transfer.
+ @param Td The first TDs of the transfer.
+ @param TimeOut TimeOut value in milliseconds.
+ @param IsLow Is Low Speed Device.
+ @param QhResult The variable to return result.
+
+ @retval EFI_SUCCESS The transfer finished with success.
+ @retval EFI_DEVICE_ERROR Transfer failed.
+
+**/
+EFI_STATUS
+OhciExecuteTransfer (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ED_HW *Ed,
+ IN UINTN TimeOut,
+ IN BOOLEAN IsLow,
+ OUT OHCI_QH_RESULT *QhResult
+ )
+{
+ UINTN Index;
+ UINTN Delay;
+ BOOLEAN Finished;
+ EFI_STATUS Status;
+
+ DEBUG((EFI_D_INIT, "+++OhciExecuteTransfer()\n"));
+
+ Finished = FALSE;
+ Status = EFI_SUCCESS;
+ Delay = (TimeOut * OHC_1_MILLISECOND / OHC_SYNC_POLL_INTERVAL) + 1;
+
+ for (Index = 0; Index < Delay; Index++) {
+ Finished = OhciCheckTdStatus (Ohc, Ed, IsLow, QhResult, HC_CLASS_CONTROL);
+
+ //
+ // Transfer is OK or some error occured (TD inactive)
+ //
+ if (Finished) {
+ DEBUG((EFI_D_INIT, "SUCCESS! OhciExecuteTransfer\n"));
+ break;
+ }
+
+ gBS->Stall (OHC_SYNC_POLL_INTERVAL);
+ }
+
+ if (!Finished) {
+ DEBUG ((EFI_D_ERROR, "OhciExecuteTransfer: execution not finished for %dms\n", (UINT32)TimeOut));
+ //OhciDumpQh (Qh);
+ //OhciDumpTds (Td);
+
+ Status = EFI_TIMEOUT;
+
+ } else if (QhResult->Result != EFI_USB_NOERROR) {
+ DEBUG ((EFI_D_ERROR, "OhciExecuteTransfer: execution failed with result %x\n", QhResult->Result));
+ //OhciDumpQh (Qh);
+ //OhciDumpTds (Td);
+
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ DEBUG((EFI_D_INIT, "---OhciExecuteTransfer()\n"));
+
+ return Status;
+}
+
+
+/**
+ Update Async Request, QH and TDs.
+
+ @param Ohc The OHCI device.
+ @param AsyncReq The OHCI asynchronous transfer to update.
+ @param Result Transfer reslut.
+ @param NextToggle The toggle of next data.
+
+**/
+VOID
+OhciUpdateAsyncReq (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ASYNC_REQUEST *AsyncReq,
+ IN UINT32 Result,
+ IN UINT32 NextToggle
+ )
+{
+ OHCI_ED_HW *EdHw;
+ OHCI_TD_SW *FirstTd;
+ OHCI_TD_SW *Td;
+ OHCI_TD_HW *TdHw;
+
+ UINT8 *DataPtr, *DataPhy;
+
+ //DEBUG((EFI_D_INIT, "+++OhciUpdateAsyncReq()\n"));
+
+ EdHw = AsyncReq->EdHw;
+ FirstTd = AsyncReq->TdSw;
+
+ if (Result == EFI_USB_NOERROR) {
+ //
+ // The last transfer succeeds. Then we need to update
+ // the Qh and Td for next round of transfer.
+ // 1. Update the TD's data toggle
+ // 2. Activate all the TDs
+ // 3. Link the TD to the queue head again since during
+ // execution, queue head's TD pointer is changed by
+ // hardware.
+ //
+
+ for (Td = FirstTd; Td != NULL; Td = Td->NextTd) {
+ TdHw = Td->TdHw;
+ if(TdHw != NULL)
+ {
+ //
+ // Allocate and map source data buffer for bus master access.
+ //
+ DataPtr = UsbHcAllocateMem (Ohc->MemPool, Td->DataLen);
+
+ if (DataPtr == NULL) {
+ DEBUG((EFI_D_ERROR, "FAIL! UsbHcAllocateMem\n"));
+ return;
+ }
+
+ DataPhy = (UINT8 *) (UINTN) UsbHcGetPciAddressForHostMem (Ohc->MemPool, DataPtr, Td->DataLen);
+
+ Ohc->Destory = Td->Data;
+ Ohc->DestroySize = Td->DataLen;
+ TdHw->current_buf_ptr = DataPhy;
+ TdHw->buffer_end = DataPhy + Td->DataLen - 1;
+ TdHw->gtd_info.b.data_toggle = NextToggle + 2;
+
+ if(Td->NextTd)
+ {
+ TdHw->next_td = Td->NextTd->TdHw;
+ }
+
+ NextToggle = NextToggle ? 0 : 1;
+ }
+ }
+
+ EdHw->head_td_ptr = FirstTd->TdHw;
+
+ //OhciDumpEd(EdHw);
+
+ OhciLinkTdToQh (Ohc, EdHw, HC_CLASS_INTERRUPT);
+
+ //DEBUG((EFI_D_INIT, "---OhciUpdateAsyncReq()\n"));
+
+ return ;
+ }
+}
+
+
+/**
+ Create Async Request node, and Link to List.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head of the transfer.
+ @param FirstTd First TD of the transfer.
+ @param DevAddr Device Address.
+ @param EndPoint EndPoint Address.
+ @param DataLen Data length.
+ @param Interval Polling Interval when inserted to frame list.
+ @param Data Data buffer, unmapped.
+ @param Callback Callback after interrupt transfeer.
+ @param Context Callback Context passed as function parameter.
+ @param IsLow Is Low Speed.
+
+ @retval EFI_SUCCESS An asynchronous transfer is created.
+ @retval EFI_INVALID_PARAMETER Paremeter is error.
+ @retval EFI_OUT_OF_RESOURCES Failed because of resource shortage.
+
+**/
+EFI_STATUS
+OhciCreateAsyncReq (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ED_HW *EdHw,
+ IN OHCI_TD_SW *TdSw,
+ IN UINT8 DevAddr,
+ IN UINT8 EndPoint,
+ IN UINTN DataLen,
+ IN UINTN Interval,
+ IN UINT8 *Data,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,
+ IN VOID *Context,
+ IN BOOLEAN IsLow
+ )
+{
+ OHCI_ASYNC_REQUEST *AsyncReq;
+
+ DEBUG((EFI_D_INIT, "+++OhciCreateAsyncReq()\n"));
+
+ AsyncReq = AllocatePool (sizeof (OHCI_ASYNC_REQUEST));
+
+ if (AsyncReq == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Fill Request field. Data is allocated host memory, not mapped
+ //
+ AsyncReq->Signature = OHCI_ASYNC_INT_SIGNATURE;
+ AsyncReq->DevAddr = DevAddr;
+ AsyncReq->EndPoint = EndPoint;
+ AsyncReq->DataLen = DataLen;
+ AsyncReq->Interval = OhciConvertPollRate(Interval);
+ AsyncReq->Data = Data;
+ AsyncReq->Callback = Callback;
+ AsyncReq->Context = Context;
+ AsyncReq->EdHw = EdHw;
+ AsyncReq->TdSw = TdSw;
+ AsyncReq->IsLow = IsLow;
+
+ //
+ // Insert the new interrupt transfer to the head of the list.
+ // The interrupt transfer's monitor function scans the whole
+ // list from head to tail. The new interrupt transfer MUST be
+ // added to the head of the list.
+ //
+ InsertHeadList (&(Ohc->AsyncIntList), &(AsyncReq->Link));
+
+ DEBUG((EFI_D_INIT, "---OhciCreateAsyncReq()\n"));
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Free an asynchronous request's resource such as memory.
+
+ @param Ohc The OHCI device.
+ @param AsyncReq The asynchronous request to free.
+
+**/
+VOID
+OhciFreeAsyncReq (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ASYNC_REQUEST *AsyncReq
+ )
+{
+ ASSERT ((Ohc != NULL) && (AsyncReq != NULL));
+
+ DEBUG((EFI_D_ERROR, "+++OhciFreeAsyncReq()\n"));
+
+ OhciDestoryTds (Ohc, AsyncReq->TdSw);
+
+ if (AsyncReq->Data != NULL) {
+ UsbHcFreeMem (Ohc->MemPool, AsyncReq->Data, AsyncReq->DataLen);
+ }
+
+ gBS->FreePool (AsyncReq);
+
+ DEBUG((EFI_D_ERROR, "+++OhciFreeAsyncReq()\n"));
+}
+
+
+/**
+ Unlink an asynchronous request's from OHC's asynchronus list.
+ also remove the queue head from the frame list. If FreeNow,
+ release its resource also. Otherwise, add the request to the
+ OHC's recycle list to wait for a while before release the memory.
+ Until then, hardware won't hold point to the request.
+
+ @param Ohc The OHCI device.
+ @param AsyncReq The asynchronous request to free.
+ @param FreeNow If TRUE, free the resource immediately, otherwise
+ add the request to recycle wait list.
+
+**/
+VOID
+OhciUnlinkAsyncReq (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ASYNC_REQUEST *AsyncReq,
+ IN BOOLEAN FreeNow
+ )
+{
+ ASSERT ((Ohc != NULL) && (AsyncReq != NULL));
+
+ DEBUG((EFI_D_INIT, "+++OhciUnlinkAsyncReq()\n"));
+#if 1
+#else
+ RemoveEntryList (&(AsyncReq->Link));
+ OhciUnlinkQhFromFrameList (Ohc, AsyncReq->QhSw);
+
+ if (FreeNow) {
+ OhciFreeAsyncReq (Ohc, AsyncReq);
+ } else {
+ //
+ // To sychronize with hardware, mark the queue head as inactive
+ // then add AsyncReq to OHC's recycle list
+ //
+ AsyncReq->QhSw->QhHw.VerticalLink = QH_VLINK (NULL, TRUE);
+ AsyncReq->Recycle = Ohc->RecycleWait;
+ Ohc->RecycleWait = AsyncReq;
+ }
+#endif
+ DEBUG((EFI_D_INIT, "---OhciUnlinkAsyncReq()\n"));
+}
+
+
+/**
+ Delete Async Interrupt QH and TDs.
+
+ @param Ohc The OHCI device.
+ @param DevAddr Device Address.
+ @param EndPoint EndPoint Address.
+ @param Toggle The next data toggle to use.
+
+ @retval EFI_SUCCESS The request is deleted.
+ @retval EFI_INVALID_PARAMETER Paremeter is error.
+ @retval EFI_NOT_FOUND The asynchronous isn't found.
+
+**/
+EFI_STATUS
+OhciRemoveAsyncReq (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DevAddr,
+ IN UINT8 EndPoint,
+ OUT UINT8 *Toggle
+ )
+{
+ EFI_STATUS Status;
+ OHCI_ASYNC_REQUEST *AsyncReq;
+ OHCI_QH_RESULT QhResult;
+ LIST_ENTRY *Link;
+ BOOLEAN Found;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // If no asynchronous interrupt transaction exists
+ //
+ if (IsListEmpty (&(Ohc->AsyncIntList))) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Find the asynchronous transfer to this device/endpoint pair
+ //
+ Found = FALSE;
+ Link = Ohc->AsyncIntList.ForwardLink;
+
+ do {
+ AsyncReq = OHCI_ASYNC_INT_FROM_LINK (Link);
+ Link = Link->ForwardLink;
+
+ if ((AsyncReq->DevAddr == DevAddr) && (AsyncReq->EndPoint == EndPoint)) {
+ Found = TRUE;
+ break;
+ }
+
+ } while (Link != &(Ohc->AsyncIntList));
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check the result of the async transfer then update it
+ // to get the next data toggle to use.
+ //
+ OhciCheckTdStatus (Ohc, AsyncReq->EdHw, AsyncReq->IsLow, &QhResult, HC_CLASS_INTERRUPT);
+ *Toggle = QhResult.NextToggle;
+
+ //
+ // Don't release the request now, keep it to synchronize with hardware.
+ //
+ OhciUnlinkAsyncReq (Ohc, AsyncReq, FALSE);
+ return Status;
+}
+
+
+/**
+ Recycle the asynchronouse request. When a queue head
+ is unlinked from frame list, host controller hardware
+ may still hold a cached pointer to it. To synchronize
+ with hardware, the request is released in two steps:
+ first it is linked to the OHC's RecycleWait list. At
+ the next time OhciMonitorAsyncReqList is fired, it is
+ moved to OHC's Recylelist. Then, at another timer
+ activation, all the requests on Recycle list is freed.
+ This guarrantes that each unlink queue head keeps
+ existing for at least 50ms, far enough for the hardware
+ to clear its cache.
+
+ @param Ohc The OHCI device.
+
+**/
+VOID
+OhciRecycleAsyncReq (
+ IN USB_HC_DEV *Ohc
+ )
+{
+ OHCI_ASYNC_REQUEST *Req;
+ OHCI_ASYNC_REQUEST *Next;
+
+ Req = Ohc->Recycle;
+
+ while (Req != NULL) {
+ Next = Req->Recycle;
+ OhciFreeAsyncReq (Ohc, Req);
+ Req = Next;
+ }
+
+ Ohc->Recycle = Ohc->RecycleWait;
+ Ohc->RecycleWait = NULL;
+}
+
+
+
+/**
+ Release all the asynchronous transfers on the lsit.
+
+ @param Ohc The OHCI device.
+
+**/
+VOID
+OhciFreeAllAsyncReq (
+ IN USB_HC_DEV *Ohc
+ )
+{
+ LIST_ENTRY *Head;
+ OHCI_ASYNC_REQUEST *AsyncReq;
+
+ DEBUG((EFI_D_INIT, "+++OhciFreeAllAsyncReq()\n"));
+
+ //
+ // Call OhciRecycleAsyncReq twice. The requests on Recycle
+ // will be released at the first call; The requests on
+ // RecycleWait will be released at the second call.
+ //
+ OhciRecycleAsyncReq (Ohc);
+ OhciRecycleAsyncReq (Ohc);
+
+ Head = &(Ohc->AsyncIntList);
+
+ if (IsListEmpty (Head)) {
+ return;
+ }
+
+ while (!IsListEmpty (Head)) {
+ AsyncReq = OHCI_ASYNC_INT_FROM_LINK (Head->ForwardLink);
+ OhciUnlinkAsyncReq (Ohc, AsyncReq, TRUE);
+ }
+
+ DEBUG((EFI_D_INIT, "---OhciFreeAllAsyncReq()\n"));
+}
+
+
+/**
+ Interrupt transfer periodic check handler.
+
+ @param Event The event of the time.
+ @param Context Context of the event, pointer to USB_HC_DEV.
+
+**/
+VOID
+EFIAPI
+OhciMonitorAsyncReqList (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ OHCI_ASYNC_REQUEST *AsyncReq;
+ LIST_ENTRY *Link;
+ USB_HC_DEV *Ohc;
+ VOID *Data;
+ BOOLEAN Finished;
+ OHCI_QH_RESULT QhResult;
+ UINT32 Inputs;
+
+ DEBUG((EFI_D_INFO, "++%a : %d\n", __FUNCTION__, __LINE__));
+
+ Ohc = (USB_HC_DEV *) Context;
+
+ //
+ // Recycle the asynchronous requests expired, and promote
+ // requests waiting to be recycled the next time when this
+ // timer expires
+ //
+
+ if(Ohc->Destory)
+ {
+ DEBUG((EFI_D_ERROR, "%a (Destoryed) : %d\n", __FUNCTION__, __LINE__));
+ UsbHcFreeMem (Ohc->MemPool, Ohc->Destory, Ohc->DestroySize);
+ Ohc->Destory = NULL;
+ Ohc->DestroySize = 0;
+ }
+ //OhciRecycleAsyncReq (Ohc);
+
+ if (IsListEmpty (&(Ohc->AsyncIntList))) {
+ DEBUG((EFI_D_ERROR, "%a (IsListEmpty) : %d\n", __FUNCTION__, __LINE__));
+ return ;
+ }
+
+ //
+ // This loop must be delete safe
+ //
+ Link = Ohc->AsyncIntList.ForwardLink;
+
+ do {
+ AsyncReq = OHCI_ASYNC_INT_FROM_LINK (Link);
+ Link = Link->ForwardLink;
+
+ Finished = OhciCheckTdStatus (Ohc, AsyncReq->EdHw, AsyncReq->IsLow, &QhResult, HC_CLASS_INTERRUPT);
+
+ if (!Finished) {
+ continue;
+ }
+
+ //
+ // Copy the data to temporary buffer if there are some
+ // data transferred. We may have zero-length packet
+ //
+ Data = NULL;
+
+ if (QhResult.Complete != 0) {
+ Data = AllocatePool (QhResult.Complete);
+
+ if (Data == NULL) {
+ return ;
+ }
+
+ CopyMem (Data, AsyncReq->TdSw->Data, QhResult.Complete);
+
+ Inputs = QhResult.Complete;
+ DEBUG((EFI_D_INIT, "INPUT : "));
+ while(Inputs--)
+ {
+ DEBUG((EFI_D_INIT, "0x%02X ", ((UINT8*)Data)[QhResult.Complete - Inputs -1]));
+ }
+ DEBUG((EFI_D_INIT, "\n"));
+ }
+
+ OhciUpdateAsyncReq (Ohc, AsyncReq, QhResult.Result, QhResult.NextToggle);
+
+ //
+ // Now, either transfer is SUCCESS or met errors since
+ // we have skipped to next transfer earlier if current
+ // transfer is still active.
+ //
+ if (QhResult.Result == EFI_USB_NOERROR) {
+ AsyncReq->Callback (Data, QhResult.Complete, AsyncReq->Context, QhResult.Result);
+ } else {
+ //
+ // Leave error recovery to its related device driver.
+ // A common case of the error recovery is to re-submit
+ // the interrupt transfer. When an interrupt transfer
+ // is re-submitted, its position in the linked list is
+ // changed. It is inserted to the head of the linked
+ // list, while this function scans the whole list from
+ // head to tail. Thus, the re-submitted interrupt transfer's
+ // callback function will not be called again in this round.
+ //
+ AsyncReq->Callback (NULL, 0, AsyncReq->Context, QhResult.Result);
+ }
+
+ if (Data != NULL) {
+ gBS->FreePool (Data);
+ }
+ } while (Link != &(Ohc->AsyncIntList));
+
+ DEBUG((EFI_D_INFO, "--%a : %d\n", __FUNCTION__, __LINE__));
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciSched.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciSched.h
new file mode 100644
index 000000000..2a3fd7c13
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/OhciSched.h
@@ -0,0 +1,270 @@
+/** @file
+
+ The definition for EHCI register operation routines.
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+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 _EFI_OHCI_SCHED_H_
+#define _EFI_OHCI_SCHED_H_
+
+
+#define OHCI_ASYNC_INT_SIGNATURE SIGNATURE_32 ('u', 'h', 'c', 'a')
+//
+// The failure mask for USB transfer return status. If any of
+// these bit is set, the transfer failed. EFI_USB_ERR_NOEXECUTE
+// and EFI_USB_ERR_NAK are not considered as error condition:
+// the transfer is still going on.
+//
+#define USB_ERR_FAIL_MASK (EFI_USB_ERR_STALL | EFI_USB_ERR_BUFFER | \
+ EFI_USB_ERR_BABBLE | EFI_USB_ERR_CRC | \
+ EFI_USB_ERR_TIMEOUT | EFI_USB_ERR_BITSTUFF | \
+ EFI_USB_ERR_SYSTEM)
+
+
+//
+// Structure to return the result of OHCI QH execution.
+// Result is the final result of the QH's QTD. NextToggle
+// is the next data toggle to use. Complete is the actual
+// length of data transferred.
+//
+typedef struct {
+ UINT32 Result;
+ UINT8 NextToggle;
+ UINTN Complete;
+} OHCI_QH_RESULT;
+
+typedef struct _OHCI_ASYNC_REQUEST OHCI_ASYNC_REQUEST;
+
+//
+// Structure used to manager the asynchronous interrupt transfers.
+//
+struct _OHCI_ASYNC_REQUEST{
+ UINTN Signature;
+ LIST_ENTRY Link;
+ OHCI_ASYNC_REQUEST *Recycle;
+
+ //
+ // Endpoint attributes
+ //
+ UINT8 DevAddr;
+ UINT8 EndPoint;
+ BOOLEAN IsLow;
+ UINTN Interval;
+
+ //
+ // Data and OHC structures
+ //
+ OHCI_TD_SW *TdSw;
+ OHCI_ED_HW *EdHw;
+ UINT8 *Data; // Allocated host memory, not mapped memory
+ UINTN DataLen;
+ VOID *Mapping;
+
+ //
+ // User callback and its context
+ //
+ EFI_ASYNC_USB_TRANSFER_CALLBACK Callback;
+ VOID *Context;
+};
+
+#define OHCI_ASYNC_INT_FROM_LINK(a) \
+ CR (a, OHCI_ASYNC_REQUEST, Link, OHCI_ASYNC_INT_SIGNATURE)
+
+
+/**
+ Create Frame List Structure.
+
+ @param Ohc The OHCI device.
+
+ @return EFI_OUT_OF_RESOURCES Can't allocate memory resources.
+ @return EFI_UNSUPPORTED Map memory fail.
+ @return EFI_SUCCESS Success.
+
+**/
+EFI_STATUS
+OhciInitFrameList (
+ IN USB_HC_DEV *Ohc
+ );
+
+/**
+ Destory FrameList buffer.
+
+ @param Ohc The OHCI device.
+
+ @return None.
+
+**/
+VOID
+OhciDestoryFrameList (
+ IN USB_HC_DEV *Ohc
+ );
+
+
+/**
+ Convert the poll rate to the maxium 2^n that is smaller
+ than Interval.
+
+ @param Interval The poll rate to convert.
+
+ @return The converted poll rate.
+
+**/
+UINTN
+OhciConvertPollRate (
+ IN UINTN Interval
+ );
+
+
+/**
+ Link a queue head (for asynchronous interrupt transfer) to
+ the frame list.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head to link into.
+
+**/
+VOID
+OhciLinkQhToFrameList (
+ USB_HC_DEV *Ohc,
+ OHCI_QH_SW *Qh
+ );
+
+
+/**
+ Unlink QH from the frame list is easier: find all
+ the precedence node, and pointer there next to QhSw's
+ next.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head to unlink.
+
+**/
+VOID
+OhciUnlinkQhFromFrameList (
+ USB_HC_DEV *Ohc,
+ OHCI_QH_SW *Qh
+ );
+
+
+/**
+ Check the result of the transfer.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head of the transfer.
+ @param Td The first TDs of the transfer.
+ @param TimeOut TimeOut value in milliseconds.
+ @param IsLow Is Low Speed Device.
+ @param QhResult The variable to return result.
+
+ @retval EFI_SUCCESS The transfer finished with success.
+ @retval EFI_DEVICE_ERROR Transfer failed.
+
+**/
+EFI_STATUS
+OhciExecuteTransfer (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ED_HW *Ed,
+ IN UINTN TimeOut,
+ IN BOOLEAN IsLow,
+ OUT OHCI_QH_RESULT *QhResult
+ );
+
+
+/**
+ Create Async Request node, and Link to List.
+
+ @param Ohc The OHCI device.
+ @param Qh The queue head of the transfer.
+ @param FirstTd First TD of the transfer.
+ @param DevAddr Device Address.
+ @param EndPoint EndPoint Address.
+ @param DataLen Data length.
+ @param Interval Polling Interval when inserted to frame list.
+ @param Data Data buffer, unmapped.
+ @param Callback Callback after interrupt transfeer.
+ @param Context Callback Context passed as function parameter.
+ @param IsLow Is Low Speed.
+
+ @retval EFI_SUCCESS An asynchronous transfer is created.
+ @retval EFI_INVALID_PARAMETER Paremeter is error.
+ @retval EFI_OUT_OF_RESOURCES Failed because of resource shortage.
+
+**/
+EFI_STATUS
+OhciCreateAsyncReq (
+ IN USB_HC_DEV *Ohc,
+ IN OHCI_ED_HW *EdHw,
+ IN OHCI_TD_SW *TdSw,
+ IN UINT8 DevAddr,
+ IN UINT8 EndPoint,
+ IN UINTN DataLen,
+ IN UINTN Interval,
+ IN UINT8 *Data,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,
+ IN VOID *Context,
+ IN BOOLEAN IsLow
+ );
+
+
+/**
+ Delete Async Interrupt QH and TDs.
+
+ @param Ohc The OHCI device.
+ @param DevAddr Device Address.
+ @param EndPoint EndPoint Address.
+ @param Toggle The next data toggle to use.
+
+ @retval EFI_SUCCESS The request is deleted.
+ @retval EFI_INVALID_PARAMETER Paremeter is error.
+ @retval EFI_NOT_FOUND The asynchronous isn't found.
+
+**/
+EFI_STATUS
+OhciRemoveAsyncReq (
+ IN USB_HC_DEV *Ohc,
+ IN UINT8 DevAddr,
+ IN UINT8 EndPoint,
+ OUT UINT8 *Toggle
+ );
+
+
+/**
+ Release all the asynchronous transfers on the lsit.
+
+ @param Ohc The OHCI device.
+
+ @return None.
+
+**/
+VOID
+OhciFreeAllAsyncReq (
+ IN USB_HC_DEV *Ohc
+ );
+
+
+/**
+ Interrupt transfer periodic check handler.
+
+ @param Event The event of the time.
+ @param Context Context of the event, pointer to USB_HC_DEV.
+
+ @return None.
+
+**/
+VOID
+EFIAPI
+OhciMonitorAsyncReqList (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/UsbHcMem.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/UsbHcMem.c
new file mode 100644
index 000000000..919c05023
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/UsbHcMem.c
@@ -0,0 +1,564 @@
+/** @file
+
+ The routine procedure for uhci memory allocate/free.
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+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 "Ohci.h"
+
+
+/**
+ Allocate a block of memory to be used by the buffer pool.
+
+ @param Pool The buffer pool to allocate memory for.
+ @param Pages How many pages to allocate.
+
+ @return The allocated memory block or NULL if failed.
+
+**/
+USBHC_MEM_BLOCK *
+UsbHcAllocMemBlock (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Pages
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ VOID *BufHost;
+ VOID *Mapping;
+ EFI_PHYSICAL_ADDRESS MappedAddr;
+ UINTN Bytes;
+ EFI_STATUS Status;
+
+ PciIo = Pool->PciIo;
+
+ Block = AllocateZeroPool (sizeof (USBHC_MEM_BLOCK));
+ if (Block == NULL) {
+ return NULL;
+ }
+
+ //
+ // each bit in the bit array represents USBHC_MEM_UNIT
+ // bytes of memory in the memory block.
+ //
+ ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
+
+ Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
+ Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
+ Block->Bits = AllocateZeroPool (Block->BitsLen);
+
+ if (Block->Bits == NULL) {
+ gBS->FreePool (Block);
+ return NULL;
+ }
+
+ //
+ // Allocate the number of Pages of memory, then map it for
+ // bus master read and write.
+ //
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ Pages,
+ &BufHost,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto FREE_BITARRAY;
+ }
+
+ Bytes = EFI_PAGES_TO_SIZE (Pages);
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ BufHost,
+ &Bytes,
+ &MappedAddr,
+ &Mapping
+ );
+
+ if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (Pages))) {
+ goto FREE_BUFFER;
+ }
+
+ //
+ // Check whether the data structure used by the host controller
+ // should be restricted into the same 4G
+ //
+ if (Pool->Check4G && (Pool->Which4G != USB_HC_HIGH_32BIT (MappedAddr))) {
+ PciIo->Unmap (PciIo, Mapping);
+ goto FREE_BUFFER;
+ }
+
+ Block->BufHost = BufHost;
+ Block->Buf = (UINT8 *) ((UINTN) MappedAddr);
+ Block->Mapping = Mapping;
+
+ return Block;
+
+FREE_BUFFER:
+ PciIo->FreeBuffer (PciIo, Pages, BufHost);
+
+FREE_BITARRAY:
+ gBS->FreePool (Block->Bits);
+ gBS->FreePool (Block);
+ return NULL;
+}
+
+
+/**
+ Free the memory block from the memory pool.
+
+ @param Pool The memory pool to free the block from.
+ @param Block The memory block to free.
+
+**/
+VOID
+UsbHcFreeMemBlock (
+ IN USBHC_MEM_POOL *Pool,
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ ASSERT ((Pool != NULL) && (Block != NULL));
+
+ PciIo = Pool->PciIo;
+
+ //
+ // Unmap the common buffer then free the structures
+ //
+ PciIo->Unmap (PciIo, Block->Mapping);
+ PciIo->FreeBuffer (PciIo, EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost);
+
+ gBS->FreePool (Block->Bits);
+ gBS->FreePool (Block);
+}
+
+
+/**
+ Alloc some memory from the block.
+
+ @param Block The memory block to allocate memory from.
+ @param Units Number of memory units to allocate.
+
+ @return EFI_SUCCESS The needed memory is allocated.
+ @return EFI_NOT_FOUND Can't find the free memory.
+
+**/
+VOID *
+UsbHcAllocMemFromBlock (
+ IN USBHC_MEM_BLOCK *Block,
+ IN UINTN Units
+ )
+{
+ UINTN Byte;
+ UINT8 Bit;
+ UINTN StartByte;
+ UINT8 StartBit;
+ UINTN Available;
+ UINTN Count;
+
+ ASSERT ((Block != 0) && (Units != 0));
+
+ StartByte = 0;
+ StartBit = 0;
+ Available = 0;
+
+ for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
+ //
+ // If current bit is zero, the corresponding memory unit is
+ // available, otherwise we need to restart our searching.
+ // Available counts the consective number of zero bit.
+ //
+ if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
+ Available++;
+
+ if (Available >= Units) {
+ break;
+ }
+
+ NEXT_BIT (Byte, Bit);
+
+ } else {
+ NEXT_BIT (Byte, Bit);
+
+ Available = 0;
+ StartByte = Byte;
+ StartBit = Bit;
+ }
+ }
+
+ if (Available < Units) {
+ return NULL;
+ }
+
+ //
+ // Mark the memory as allocated
+ //
+ Byte = StartByte;
+ Bit = StartBit;
+
+ for (Count = 0; Count < Units; Count++) {
+ ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
+
+ Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) USB_HC_BIT (Bit));
+ NEXT_BIT (Byte, Bit);
+ }
+
+ return Block->Buf + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
+}
+
+/**
+ Calculate the corresponding pci bus address according to the Mem parameter.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The pointer to host memory.
+ @param Size The size of the memory region.
+
+ @return the pci memory address
+**/
+EFI_PHYSICAL_ADDRESS
+UsbHcGetPciAddressForHostMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ UINTN AllocSize;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ UINTN Offset;
+
+ Head = Pool->Head;
+ AllocSize = USBHC_MEM_ROUND (Size);
+
+ if (Mem == NULL) {
+ return 0;
+ }
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ //
+ // scan the memory block list for the memory block that
+ // completely contains the allocated memory.
+ //
+ if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {
+ break;
+ }
+ }
+
+ ASSERT ((Block != NULL));
+ //
+ // calculate the pci memory address for host memory address.
+ //
+ Offset = (UINT8 *)Mem - Block->BufHost;
+ PhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->Buf + Offset);
+ return PhyAddr;
+}
+
+/**
+ Insert the memory block to the pool's list of the blocks.
+
+ @param Head The head of the memory pool's block list.
+ @param Block The memory block to insert.
+
+**/
+VOID
+UsbHcInsertMemBlockToPool (
+ IN USBHC_MEM_BLOCK *Head,
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ ASSERT ((Head != NULL) && (Block != NULL));
+ Block->Next = Head->Next;
+ Head->Next = Block;
+}
+
+
+/**
+ Is the memory block empty?
+
+ @param Block The memory block to check.
+
+ @return TRUE The memory block is empty.
+ @return FALSE The memory block isn't empty.
+
+**/
+BOOLEAN
+UsbHcIsMemBlockEmpty (
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < Block->BitsLen; Index++) {
+ if (Block->Bits[Index] != 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Unlink the memory block from the pool's list.
+
+ @param Head The block list head of the memory's pool.
+ @param BlockToUnlink The memory block to unlink.
+
+**/
+VOID
+UsbHcUnlinkMemBlock (
+ IN USBHC_MEM_BLOCK *Head,
+ IN USBHC_MEM_BLOCK *BlockToUnlink
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+
+ ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ if (Block->Next == BlockToUnlink) {
+ Block->Next = BlockToUnlink->Next;
+ BlockToUnlink->Next = NULL;
+ break;
+ }
+ }
+}
+
+
+/**
+ Initialize the memory management pool for the host controller.
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param Check4G Whether the host controller requires allocated memory
+ from one 4G address space.
+ @param Which4G The 4G memory area each memory allocated should be from.
+
+ @return EFI_SUCCESS The memory pool is initialized.
+ @return EFI_OUT_OF_RESOURCE Fail to init the memory pool.
+
+**/
+USBHC_MEM_POOL *
+UsbHcInitMemPool (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN BOOLEAN Check4G,
+ IN UINT32 Which4G
+ )
+{
+ USBHC_MEM_POOL *Pool;
+
+ Pool = AllocatePool (sizeof (USBHC_MEM_POOL));
+
+ if (Pool == NULL) {
+ return Pool;
+ }
+
+ Pool->PciIo = PciIo;
+ Pool->Check4G = Check4G;
+ Pool->Which4G = Which4G;
+ Pool->Head = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);
+
+ if (Pool->Head == NULL) {
+ gBS->FreePool (Pool);
+ Pool = NULL;
+ }
+
+ return Pool;
+}
+
+
+/**
+ Release the memory management pool.
+
+ @param Pool The USB memory pool to free.
+
+ @return EFI_SUCCESS The memory pool is freed.
+ @return EFI_DEVICE_ERROR Failed to free the memory pool.
+
+**/
+EFI_STATUS
+UsbHcFreeMemPool (
+ IN USBHC_MEM_POOL *Pool
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+
+ ASSERT (Pool->Head != NULL);
+
+ //
+ // Unlink all the memory blocks from the pool, then free them.
+ // UsbHcUnlinkMemBlock can't be used to unlink and free the
+ // first block.
+ //
+ for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
+ UsbHcUnlinkMemBlock (Pool->Head, Block);
+ UsbHcFreeMemBlock (Pool, Block);
+ }
+
+ UsbHcFreeMemBlock (Pool, Pool->Head);
+ gBS->FreePool (Pool);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Allocate some memory from the host controller's memory pool
+ which can be used to communicate with host controller.
+
+ @param Pool The host controller's memory pool.
+ @param Size Size of the memory to allocate.
+
+ @return The allocated memory or NULL.
+
+**/
+VOID *
+UsbHcAllocateMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ USBHC_MEM_BLOCK *NewBlock;
+ VOID *Mem;
+ UINTN AllocSize;
+ UINTN Pages;
+
+ Mem = NULL;
+ AllocSize = USBHC_MEM_ROUND (Size);
+ Head = Pool->Head;
+ ASSERT (Head != NULL);
+
+ //
+ // First check whether current memory blocks can satisfy the allocation.
+ //
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
+
+ if (Mem != NULL) {
+ ZeroMem (Mem, Size);
+ break;
+ }
+ }
+
+ if (Mem != NULL) {
+ return Mem;
+ }
+
+ //
+ // Create a new memory block if there is not enough memory
+ // in the pool. If the allocation size is larger than the
+ // default page number, just allocate a large enough memory
+ // block. Otherwise allocate default pages.
+ //
+ if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
+ Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
+ } else {
+ Pages = USBHC_MEM_DEFAULT_PAGES;
+ }
+
+ NewBlock = UsbHcAllocMemBlock (Pool, Pages);
+
+ if (NewBlock == NULL) {
+ DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));
+ return NULL;
+ }
+
+ //
+ // Add the new memory block to the pool, then allocate memory from it
+ //
+ UsbHcInsertMemBlockToPool (Head, NewBlock);
+ Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
+
+ if (Mem != NULL) {
+ ZeroMem (Mem, Size);
+ }
+
+ return Mem;
+}
+
+
+/**
+ Free the allocated memory back to the memory pool.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The memory to free.
+ @param Size The size of the memory to free.
+
+**/
+VOID
+UsbHcFreeMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ UINT8 *ToFree;
+ UINTN AllocSize;
+ UINTN Byte;
+ UINTN Bit;
+ UINTN Count;
+
+ Head = Pool->Head;
+ AllocSize = USBHC_MEM_ROUND (Size);
+ ToFree = (UINT8 *) Mem;
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ //
+ // scan the memory block list for the memory block that
+ // completely contains the memory to free.
+ //
+ if ((Block->Buf <= ToFree) && ((ToFree + AllocSize) <= (Block->Buf + Block->BufLen))) {
+ //
+ // compute the start byte and bit in the bit array
+ //
+ Byte = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) / 8;
+ Bit = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) % 8;
+
+ //
+ // reset associated bits in bit arry
+ //
+ for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
+ ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
+
+ Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
+ NEXT_BIT (Byte, Bit);
+ }
+
+ break;
+ }
+ }
+
+ //
+ // If Block == NULL, it means that the current memory isn't
+ // in the host controller's pool. This is critical because
+ // the caller has passed in a wrong memory point
+ //
+ ASSERT (Block != NULL);
+
+ //
+ // Release the current memory block if it is empty and not the head
+ //
+ if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
+ UsbHcUnlinkMemBlock (Head, Block);
+ UsbHcFreeMemBlock (Pool, Block);
+ }
+
+ return ;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/UsbHcMem.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/UsbHcMem.h
new file mode 100644
index 000000000..5192abd2f
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/OhciDxe/UsbHcMem.h
@@ -0,0 +1,161 @@
+/** @file
+
+ This file contains the definination for host controller memory management routines
+
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+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 _EFI_EHCI_MEM_H_
+#define _EFI_EHCI_MEM_H_
+
+#define USB_HC_BIT(a) ((UINTN)(1 << (a)))
+
+#define USB_HC_BIT_IS_SET(Data, Bit) \
+ ((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))
+
+#define USB_HC_HIGH_32BIT(Addr64) \
+ ((UINT32)(RShiftU64((UINTN)(Addr64), 32) & 0XFFFFFFFF))
+
+
+typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;
+struct _USBHC_MEM_BLOCK {
+ UINT8 *Bits; // Bit array to record which unit is allocated
+ UINTN BitsLen;
+ UINT8 *Buf;
+ UINT8 *BufHost;
+ UINTN BufLen; // Memory size in bytes
+ VOID *Mapping;
+ USBHC_MEM_BLOCK *Next;
+};
+
+//
+// USBHC_MEM_POOL is used to manage the memory used by USB
+// host controller. EHCI requires the control memory and transfer
+// data to be on the same 4G memory.
+//
+typedef struct _USBHC_MEM_POOL {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ BOOLEAN Check4G;
+ UINT32 Which4G;
+ USBHC_MEM_BLOCK *Head;
+} USBHC_MEM_POOL;
+
+//
+// Memory allocation unit, must be 2^n, n>4
+//
+#define USBHC_MEM_UNIT 64
+
+#define USBHC_MEM_UNIT_MASK (USBHC_MEM_UNIT - 1)
+#define USBHC_MEM_DEFAULT_PAGES 16
+
+#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))
+
+//
+// Advance the byte and bit to the next bit, adjust byte accordingly.
+//
+#define NEXT_BIT(Byte, Bit) \
+ do { \
+ (Bit)++; \
+ if ((Bit) > 7) { \
+ (Byte)++; \
+ (Bit) = 0; \
+ } \
+ } while (0)
+
+
+/**
+ Initialize the memory management pool for the host controller.
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param Check4G Whether the host controller requires allocated memory
+ from one 4G address space.
+ @param Which4G The 4G memory area each memory allocated should be from.
+
+ @retval EFI_SUCCESS The memory pool is initialized.
+ @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
+
+**/
+USBHC_MEM_POOL *
+UsbHcInitMemPool (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN BOOLEAN Check4G,
+ IN UINT32 Which4G
+ );
+
+
+/**
+ Release the memory management pool.
+
+ @param Pool The USB memory pool to free.
+
+ @return EFI_SUCCESS The memory pool is freed.
+ @return EFI_DEVICE_ERROR Failed to free the memory pool.
+
+**/
+EFI_STATUS
+UsbHcFreeMemPool (
+ IN USBHC_MEM_POOL *Pool
+ );
+
+
+
+/**
+ Allocate some memory from the host controller's memory pool
+ which can be used to communicate with host controller.
+
+ @param Pool The host controller's memory pool.
+ @param Size Size of the memory to allocate.
+
+ @return The allocated memory or NULL.
+
+**/
+VOID *
+UsbHcAllocateMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Size
+ );
+
+
+
+/**
+ Free the allocated memory back to the memory pool.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The memory to free.
+ @param Size The size of the memory to free.
+
+ @return None.
+
+**/
+VOID
+UsbHcFreeMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ );
+
+/**
+ Calculate the corresponding pci bus address according to the Mem parameter.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The pointer to host memory.
+ @param Size The size of the memory region.
+
+ @return the pci memory address
+**/
+EFI_PHYSICAL_ADDRESS
+UsbHcGetPciAddressForHostMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ );
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB.c
new file mode 100644
index 000000000..e89ba4b0a
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB.c
@@ -0,0 +1,353 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ 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 <Uefi.h>
+#include <Exynos5_USB2Phy.h>
+#include <Exynos5_USB3Phy.h>
+#include <Exynos5_USB3Drd.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/ExynosGpio.h>
+#include <Platform/ArmPlatform.h>
+
+#define PHY_ENABLE (1 << 0)
+#define PHY_DISABLE (0)
+
+enum usb_phy_type {
+ USB_PHY = (0x1 << 0),
+ USB_PHY0 = (0x1 << 0),
+ USB_PHY1 = (0x1 << 1),
+ USB_PHY_HSIC0 = (0x1 << 1),
+ USB_PHY_HSIC1 = (0x1 << 2),
+};
+
+
+static void usb_clk_get(enum usb_clk_type clk_type)
+{
+ if( clk_type == USBOTG_CLK) {
+ MmioWrite32(CLK_GATE_IP_FSYS, MmioRead32(CLK_GATE_IP_FSYS) | (1<<7));
+ } else if( clk_type == USBHOST_CLK) {
+ MmioWrite32(CLK_GATE_IP_FSYS, MmioRead32(CLK_GATE_IP_FSYS) | (1<<18));
+ } else if( clk_type == USBDRD30_CLK) {
+ MmioWrite32(CLK_GATE_IP_FSYS, MmioRead32(CLK_GATE_IP_FSYS) | (1<<19));
+ } else {
+ DEBUG ((EFI_D_ERROR, "FAIL! usb_clk_get\n"));
+ }
+
+ return;
+}
+
+static void usb_clk_put(enum usb_clk_type clk_type)
+{
+ if( clk_type == USBOTG_CLK) {
+ MmioWrite32(CLK_GATE_IP_FSYS, MmioRead32(CLK_GATE_IP_FSYS) & ~ (1<<7));
+ } else if( clk_type == USBHOST_CLK) {
+ MmioWrite32(CLK_GATE_IP_FSYS, MmioRead32(CLK_GATE_IP_FSYS) & ~ (1<<18));
+ } else if( clk_type == USBDRD30_CLK) {
+ MmioWrite32(CLK_GATE_IP_FSYS, MmioRead32(CLK_GATE_IP_FSYS) & ~ (1<<19));
+ } else {
+ DEBUG ((EFI_D_ERROR, "FAIL! usb_clk_get\n"));
+ }
+
+ return;
+}
+
+//------------------------------------------------------------------------------------
+
+//////////
+// Function Name : USBPHY_Ctr48MhzClk
+// Function Desctiption : This function sets clk48m_ohci in Suspend Mode.
+// Input : NONE
+// Output : NONE
+// Version :
+void USBPHY_Ctr48MhzClk(UINT8 bEnable_48Mhz)
+{
+
+ UINT32 uTemp;
+
+ uTemp = MmioRead32(rUPHY_OHCICTRL);
+ uTemp &= ~(1<<2);
+ uTemp |= bEnable_48Mhz<<2;
+ MmioWrite32(rUPHY_OHCICTRL, uTemp);
+}
+
+static int exynos5_usb_host_phy20_is_on(void)
+{
+ return (MmioRead32(EXYNOS5_USB2_PHY_HOST_CTRL0) & HOST_CTRL0_PHYSWRSTALL) ? 0 : 1;
+}
+
+static void exynos5_usb_phy_control(enum usb_phy_type phy_type , int on)
+{
+ if (phy_type & USB_PHY0)
+ MmioWrite32(EXYNOS5_USBDEV_PHY_CONTROL, on);
+ if (phy_type & USB_PHY1)
+ MmioWrite32(EXYNOS5_USBHOST_PHY_CONTROL, on);
+}
+
+void exynos5_usb_phy20_init(void)
+{
+ EFI_STATUS Status;
+ EXYNOS_GPIO *Gpio;
+ UINT32 hostphy_ctrl0;
+ UINT32 hsic_ctrl;
+ UINT32 ehcictrl;
+
+ DEBUG ((EFI_D_ERROR, "exynos5_usb_phy20_init START $$$\n"));
+
+ Status = gBS->LocateProtocol(&gSamsungPlatformGpioProtocolGuid, NULL, (VOID **)&Gpio);
+ ASSERT_EFI_ERROR(Status);
+
+ if(PcdGetBool(PcdExynos5250Evt1))
+ {
+ Gpio->Set(Gpio, USB_2_EVT1, GPIO_MODE_OUTPUT_1);
+ Gpio->SetPull(Gpio, USB_2_EVT1, GPIO_PULL_NONE);
+ }
+
+ if (exynos5_usb_host_phy20_is_on())
+ {
+ DEBUG ((EFI_D_ERROR, "Already power on PHY $$$\n"));
+ return;
+ }
+
+ // Must be enable usbhost & usbotg clk
+ usb_clk_get(USBHOST_CLK);
+ usb_clk_get(USBOTG_CLK);
+
+ MmioWrite32(ETC6PUD, (MmioRead32(ETC6PUD) & ~(0x3 << 14)) | (0x3 << 14));
+
+ exynos5_usb_phy_control(USB_PHY1, PHY_ENABLE);
+
+ /* Host and Device should be set at the same time */
+ hostphy_ctrl0 = MmioRead32(EXYNOS5_USB2_PHY_HOST_CTRL0);
+ hostphy_ctrl0 &= ~(HOST_CTRL0_FSEL_MASK);
+
+ /* 2.0 phy reference clock configuration */
+ // default reference clock 24MZ
+ hostphy_ctrl0 |= CLKSEL_24M;
+
+ /* COMMON Block configuration during suspend */
+ hostphy_ctrl0 &= ~(HOST_CTRL0_COMMONONN);
+
+ /* host phy reset */
+ hostphy_ctrl0 &= ~(HOST_CTRL0_PHYSWRST | HOST_CTRL0_PHYSWRSTALL | HOST_CTRL0_SIDDQ);
+ hostphy_ctrl0 &= ~(HOST_CTRL0_FORCESUSPEND | HOST_CTRL0_FORCESLEEP);
+ hostphy_ctrl0 |= (HOST_CTRL0_LINKSWRST | HOST_CTRL0_UTMISWRST);
+ MmioWrite32(EXYNOS5_USB2_PHY_HOST_CTRL0, hostphy_ctrl0);
+ MicroSecondDelay(10);
+ MicroSecondDelay(10);
+ hostphy_ctrl0 &= ~(HOST_CTRL0_LINKSWRST | HOST_CTRL0_UTMISWRST);
+ MmioWrite32(EXYNOS5_USB2_PHY_HOST_CTRL0, hostphy_ctrl0);
+
+ DEBUG ((EFI_D_ERROR, "exynos5_usb_phy20_init Clk set $$$\n"));
+
+ /* HSIC phy reset */
+ hsic_ctrl = (HSIC_CTRL_REFCLKDIV(0x24) | HSIC_CTRL_REFCLKSEL(0x2) |HSIC_CTRL_PHYSWRST);
+ MmioWrite32(PHY_HSIC_CTRL1, hsic_ctrl);
+ MmioWrite32(PHY_HSIC_CTRL2, hsic_ctrl);
+ MicroSecondDelay(10);
+ MicroSecondDelay(10);
+ hsic_ctrl = (HSIC_CTRL_REFCLKDIV(0x24) | HSIC_CTRL_REFCLKSEL(0x2));
+ MmioWrite32(PHY_HSIC_CTRL1, hsic_ctrl);
+ MmioWrite32(PHY_HSIC_CTRL2, hsic_ctrl);
+
+ MicroSecondDelay(80);
+ MicroSecondDelay(80);
+
+ /* enable EHCI DMA burst */
+ ehcictrl = MmioRead32(PHY_HOST_EHCICTRL);
+ ehcictrl |= (EHCICTRL_ENAINCRXALIGN | EHCICTRL_ENAINCR4 |EHCICTRL_ENAINCR8 | EHCICTRL_ENAINCR16);
+ MmioWrite32(PHY_HOST_EHCICTRL, ehcictrl);
+
+ DEBUG ((EFI_D_ERROR, "exynos5_usb_phy20_init END $$$\n"));
+}
+
+void exynos5_usb_phy20_off(void)
+{
+ UINT32 uTemp;
+
+ uTemp = MmioRead32(rUPHY_USBCTRL0);
+ uTemp |= (0x1<<9);
+ MmioWrite32(rUPHY_USBCTRL0, uTemp);
+
+ usb_clk_put(USBOTG_CLK);
+ usb_clk_put(USBHOST_CLK);
+}
+
+
+void exynos5_usb_phy30_init(void)
+{
+ UINT32 reg;
+ DEBUG ((EFI_D_ERROR, "exynos5_usb_phy30_init START $$$\n"));
+
+ MmioWrite32(0x10020548, 0x0BF00000);
+ usb_clk_get(USBDRD30_CLK);
+
+ exynos5_usb_phy_control(USB_PHY0, PHY_ENABLE);
+
+ /* Reset USB 3.0 PHY */
+ MmioWrite32(EXYNOS_USB3_PHYREG0, 0x00000000);
+ MmioWrite32(EXYNOS_USB3_PHYPARAM0, 0x24d4e6e4);
+ MmioWrite32(EXYNOS_USB3_PHYRESUME, 0x00000000);
+
+ if(PcdGetBool(PcdExynos5250Evt1))
+ {
+ MmioWrite32(EXYNOS_USB3_LINKSYSTEM, 0x08000000);
+ MmioWrite32(EXYNOS_USB3_PHYPARAM1, 0x03fff81C);
+ MmioWrite32(EXYNOS_USB3_PHYBATCHG, 0x00000004);
+ } else {
+ MmioWrite32(EXYNOS_USB3_LINKSYSTEM, 0x087FFFC0);
+ MmioWrite32(EXYNOS_USB3_PHYPARAM1, 0x03fff820);
+ MmioWrite32(EXYNOS_USB3_PHYBATCHG, 0x00000000);
+ MmioWrite32(EXYNOS_USB3_LINKPORT, (MmioRead32(EXYNOS_USB3_LINKPORT) & ~(0x3<<4)) |(0x3<<2));
+ }
+
+ /* UTMI Power Control */
+ MmioWrite32(EXYNOS_USB3_PHYUTMI, EXYNOS_USB3_PHYUTMI_OTGDISABLE);
+
+ if(PcdGetBool(PcdExynos5250Evt1))
+ {
+ /* Set 100MHz external clock */
+ reg = EXYNOS_USB3_PHYCLKRST_PORTRESET |
+ /* HS PLL uses ref_pad_clk{p,m} or ref_alt_clk_{p,m}
+ * as reference */
+ EXYNOS_USB3_PHYCLKRST_REFCLKSEL(3) |
+ /* Digital power supply in normal operating mode */
+ EXYNOS_USB3_PHYCLKRST_RETENABLEN |
+ /* 0x27-100MHz, 0x2a-24MHz, 0x31-20MHz, 0x38-19.2MHz */
+ EXYNOS_USB3_PHYCLKRST_FSEL(0x5) |
+ /* 0x19-100MHz, 0x68-24MHz, 0x7d-20Mhz */
+ EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER(0x68) |
+ EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL(0x88) |
+ /* Enable ref clock for SS function */
+ EXYNOS_USB3_PHYCLKRST_REF_SSP_EN |
+ /* Enable spread spectrum */
+ EXYNOS_USB3_PHYCLKRST_SSC_EN;
+ } else {
+ /* Set 100MHz external clock */
+ reg = EXYNOS_USB3_PHYCLKRST_PORTRESET |
+ /* HS PLL uses ref_pad_clk{p,m} or ref_alt_clk_{p,m}
+ * as reference */
+ EXYNOS_USB3_PHYCLKRST_REFCLKSEL(2) |
+ /* Digital power supply in normal operating mode */
+ EXYNOS_USB3_PHYCLKRST_RETENABLEN |
+ /* 0x27-100MHz, 0x2a-24MHz, 0x31-20MHz, 0x38-19.2MHz */
+ EXYNOS_USB3_PHYCLKRST_FSEL(0x27) |
+ /* 0x19-100MHz, 0x68-24MHz, 0x7d-20Mhz */
+ EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER(0x19) |
+ EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL(0x00) |
+ /* Enable ref clock for SS function */
+ EXYNOS_USB3_PHYCLKRST_REF_SSP_EN |
+ /* Enable spread spectrum */
+ EXYNOS_USB3_PHYCLKRST_SSC_EN |
+ EXYNOS_USB3_PHYCLKRST_COMMONONN;
+ }
+ MmioWrite32(EXYNOS_USB3_PHYCLKRST, reg);
+
+ MicroSecondDelay(10);
+ MicroSecondDelay(10);
+
+ reg &= ~(EXYNOS_USB3_PHYCLKRST_PORTRESET);
+
+ MmioWrite32(EXYNOS_USB3_PHYCLKRST, reg);
+ DEBUG ((EFI_D_ERROR, "exynos5_usb_phy30_init END $$$\n"));
+
+}
+
+void exynos_xhci_phy_set(void)
+{
+ /* The reset values:
+ * GUSB2PHYCFG(0) = 0x00002400
+ * GUSB3PIPECTL(0) = 0x00260002
+ */
+ // orr32
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GCTL,
+ (MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GCTL) | EXYNOS_USB3_GCTL_CoreSoftReset));
+ // orr32
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB2PHYCFG(0),
+ (MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB2PHYCFG(0)) | EXYNOS_USB3_GUSB2PHYCFGx_PHYSoftRst));
+ // orr32
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB3PIPECTL(0),
+ (MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB3PIPECTL(0)) | EXYNOS_USB3_GUSB3PIPECTLx_PHYSoftRst));
+
+ exynos5_usb_phy30_init();
+
+ // bic32
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB2PHYCFG(0),
+ (MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB2PHYCFG(0)) & ~EXYNOS_USB3_GUSB2PHYCFGx_PHYSoftRst));
+ // bic32
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB3PIPECTL(0),
+ (MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB3PIPECTL(0)) & ~EXYNOS_USB3_GUSB3PIPECTLx_PHYSoftRst));
+ // bic32
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GCTL,
+ (MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GCTL) & ~EXYNOS_USB3_GCTL_CoreSoftReset));
+ // bic32
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB2PHYCFG(0),
+ (MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB2PHYCFG(0)) & ~(EXYNOS_USB3_GUSB2PHYCFGx_SusPHY |
+ EXYNOS_USB3_GUSB2PHYCFGx_EnblSlpM |
+ EXYNOS_USB3_GUSB2PHYCFGx_USBTrdTim_MASK)));
+
+ // orr32
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB2PHYCFG(0),
+ (MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB2PHYCFG(0)) | EXYNOS_USB3_GUSB2PHYCFGx_USBTrdTim(9)));
+
+ // bic32
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB3PIPECTL(0),
+ (MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB3PIPECTL(0)) & ~EXYNOS_USB3_GUSB3PIPECTLx_SuspSSPhy));
+
+
+ DEBUG ((EFI_D_ERROR, "GUSB2PHYCFG(0)=0x%08x, GUSB3PIPECTL(0)=0x%08x\n",
+ MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB2PHYCFG(0)),
+ MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GUSB3PIPECTL(0))));
+
+ /* Global core init */
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GSBUSCFG0,
+ EXYNOS_USB3_GSBUSCFG0_INCR16BrstEna |
+ EXYNOS_USB3_GSBUSCFG0_INCR8BrstEna |
+ EXYNOS_USB3_GSBUSCFG0_INCR4BrstEna);
+
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GSBUSCFG1,
+ EXYNOS_USB3_GSBUSCFG1_BREQLIMIT(0x3));
+
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GTXTHRCFG, 0x0);
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GRXTHRCFG, 0x0);
+}
+
+UINT32 exynos_xhci_change_mode(void)
+{
+ UINT32 gctl;
+
+ gctl = MmioRead32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GCTL);
+ gctl &= ~(EXYNOS_USB3_GCTL_PrtCapDir_MASK |
+ EXYNOS_USB3_GCTL_FRMSCLDWN_MASK |
+ EXYNOS_USB3_GCTL_RAMClkSel_MASK);
+
+ gctl |= (EXYNOS_USB3_GCTL_FRMSCLDWN(0x1e85) | /* Power Down Scale */
+ EXYNOS_USB3_GCTL_RAMClkSel(0x2) | /* Ram Clock Select */
+ EXYNOS_USB3_GCTL_DisScramble);
+
+ gctl |= EXYNOS_USB3_GCTL_PrtCapDir(0x1);/* 0x1 : Host */
+
+ MmioWrite32(EXYNOS5_USB3_DRD_BASEADDR + EXYNOS_USB3_GCTL, gctl);
+
+ DEBUG ((EFI_D_ERROR, "Change xHCI host mode %x\n", gctl));
+ return gctl;
+}
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB2Phy.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB2Phy.h
new file mode 100644
index 000000000..fce6ca830
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB2Phy.h
@@ -0,0 +1,114 @@
+#ifndef _EFI_EXYNOS5_USB2_PHY_H_
+#define _EFI_EXYNOS5_USB2_PHY_H_
+
+#define USB_XHCI_HCCAPBASE (0x12000000) //Gaia
+#define USB_EHCI_HCCAPBASE (0x12110000) //Gaia
+#define USB_OHCI_HCCAPBASE (USB_EHCI_HCCAPBASE + 0x10000)
+
+#define EXYNOS5_USB2_PHY_HOST_CTRL0 0x12130000 //Gaia
+
+#define HOST_CTRL0_PHYSWRSTALL (0x1 << 31)
+#define CLKSEL_50M (0x7 << 16)
+#define CLKSEL_24M (0x5 << 16)
+#define CLKSEL_20M (0x4 << 16)
+#define CLKSEL_19200K (0x3 << 16)
+#define CLKSEL_12M (0x2 << 16)
+#define CLKSEL_10M (0x1 << 16)
+#define CLKSEL_9600K (0x0 << 16)
+#define HOST_CTRL0_FSEL_MASK (0x7 << 16)
+#define HOST_CTRL0_COMMONONN (0x1 << 9)
+#define HOST_CTRL0_PHYSWRST (0x1 << 0)
+#define HOST_CTRL0_SIDDQ (0x1 << 6)
+#define HOST_CTRL0_FORCESLEEP (0x1 << 5)
+#define HOST_CTRL0_FORCESUSPEND (0x1 << 4)
+#define HOST_CTRL0_LINKSWRST (0x1 << 1)
+#define HOST_CTRL0_UTMISWRST (0x1 << 2)
+#define HSIC_CTRL_REFCLKDIV(val) ((val&0x7f) << 16)
+#define HSIC_CTRL_REFCLKSEL(val) ((val&0x3) << 23)
+#define HSIC_CTRL_PHYSWRST (0x1 << 0)
+#define PHY_HSIC_CTRL1 (EXYNOS5_USB2_PHY_HOST_CTRL0 + 0x10)
+#define PHY_HSIC_CTRL2 (EXYNOS5_USB2_PHY_HOST_CTRL0 + 0x20)
+#define PHY_HOST_EHCICTRL (EXYNOS5_USB2_PHY_HOST_CTRL0 + 0x30)
+#define EHCICTRL_ENAINCRXALIGN (0x1 << 29)
+#define EHCICTRL_ENAINCR4 (0x1 << 28)
+#define EHCICTRL_ENAINCR8 (0x1 << 27)
+#define EHCICTRL_ENAINCR16 (0x1 << 26)
+
+//CMU
+#define CLK_GATE_IP_FSYS 0x10020944 //GAIA
+
+//GPIO
+#define ETC6PUD (0x114002A8) //(0x11400000 + 0x2A8)
+
+//PMU
+#define EXYNOS5_USBDEV_PHY_CONTROL (0x10040000 + 0x0704)
+#define EXYNOS5_USBHOST_PHY_CONTROL (0x10040000 + 0x0708)
+
+
+//--------------------- for gaia ----------
+#define UHOST_FIN 48000000
+#define USBDEV_FIN 12000000
+
+#define USBHOST_AHB_INCR16 0x2000000
+#define USBHOST_AHB_INCR8 0x1000000
+#define USBHOST_AHB_INCR4 0x0800000
+#define USBHOST_AHB_INCRs 0x3800000
+#define USBHOST_AHB_INCRx 0x3c00000
+#define USBHOST_AHB_SINGLE 0x0000000
+
+typedef enum
+{
+ REFCLK_XTAL = 0x0, //XO : form Crystal
+ REFCLK_OSC = 0x1, //XO : OSC 1.8V Clock
+ REFCLK_PLL = 0x2, //PLL form CLKCORE
+}USBPHY_REFCLK;
+
+typedef enum
+{
+ FSEL_9_6M = 0x0,
+ FSEL_10M = 0x1,
+ FSEL_12M = 0x2,
+ FSEL_19_2M = 0x3,
+ FSEL_20M = 0x4,
+ FSEL_24M = 0x5,
+ FSEL_48M = 0x6, //Reserved
+ FSEL_50M = 0x7,
+}USBPHY_REFSEL;
+
+#define USBPHY_RETENABLE 1 //Retention Mode Enable == 1, Normal Operation mode must be 1.
+
+void USBPHY_Ctr48MhzClk(UINT8 bEnable_48Mhz);
+void usb_host_phy_off(void);
+
+//-------------------------------------------------------
+//OTG
+
+enum USBPHY_CON_SFR
+{
+ rUPHY_USBCTRL0 = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0000,
+ rUPHY_USBTUNE0 = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0004,
+ rUPHY_HSICCTRL1 = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0010,
+ rUPHY_HSICTUNE1 = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0014,
+ rUPHY_HSICCTRL2 = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0020,
+ rUPHY_HSICTUNE2 = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0024,
+
+ rUPHY_EHCICTRL = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0030,
+ rUPHY_OHCICTRL = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0034,
+
+ rUPHY_USBOTG_SYS = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0038,
+ rUPHY_USBOTG_TUNE = EXYNOS5_USB2_PHY_HOST_CTRL0+0x0040,
+};
+
+enum usb_clk_type {
+ USBOTG_CLK, USBHOST_CLK, USBDRD30_CLK
+};
+
+//-------------------------------------------------------
+// Functions
+//-------------------------------------------------------
+
+void exynos5_usb_phy20_init(void);
+
+#endif
+
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB3Drd.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB3Drd.h
new file mode 100644
index 000000000..09b66e1d5
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB3Drd.h
@@ -0,0 +1,403 @@
+/* include/linux/usb/exynos_usb3_drd.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co. Ltd
+ * Author: Anton Tikhomirov <av.tikhomirov@samsung.com>
+ *
+ * Exynos SuperSpeed USB 3.0 DRD Controller global and OTG registers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_USB_EXYNOS_USB3_DRD_H
+#define __LINUX_USB_EXYNOS_USB3_DRD_H
+
+#define EXYNOS5_USB3_DRD_BASEADDR 0x12000000
+
+/* Global registers */
+#define EXYNOS_USB3_GSBUSCFG0 0xC100
+#define EXYNOS_USB3_GSBUSCFG0_SBusStoreAndForward (1 << 12)
+#define EXYNOS_USB3_GSBUSCFG0_DatBigEnd (1 << 11)
+#define EXYNOS_USB3_GSBUSCFG0_INCR256BrstEna (1 << 7)
+#define EXYNOS_USB3_GSBUSCFG0_INCR128BrstEna (1 << 6)
+#define EXYNOS_USB3_GSBUSCFG0_INCR64BrstEna (1 << 5)
+#define EXYNOS_USB3_GSBUSCFG0_INCR32BrstEna (1 << 4)
+#define EXYNOS_USB3_GSBUSCFG0_INCR16BrstEna (1 << 3)
+#define EXYNOS_USB3_GSBUSCFG0_INCR8BrstEna (1 << 2)
+#define EXYNOS_USB3_GSBUSCFG0_INCR4BrstEna (1 << 1)
+#define EXYNOS_USB3_GSBUSCFG0_INCRBrstEna (1 << 0)
+
+#define EXYNOS_USB3_GSBUSCFG1 0xC104
+#define EXYNOS_USB3_GSBUSCFG1_EN1KPAGE (1 << 12)
+#define EXYNOS_USB3_GSBUSCFG1_BREQLIMIT_MASK (0xf << 8)
+#define EXYNOS_USB3_GSBUSCFG1_BREQLIMIT_SHIFT 8
+#define EXYNOS_USB3_GSBUSCFG1_BREQLIMIT(_x) ((_x) << 8)
+
+#define EXYNOS_USB3_GTXTHRCFG 0xC108
+#define EXYNOS_USB3_GTXTHRCFG_USBTxPktCntSel (1 << 29)
+#define EXYNOS_USB3_GTXTHRCFG_USBTxPktCnt_MASK (0xf << 24)
+#define EXYNOS_USB3_GTXTHRCFG_USBTxPktCnt_SHIFT 24
+#define EXYNOS_USB3_GTXTHRCFG_USBTxPktCnt(_x) ((_x) << 24)
+#define EXYNOS_USB3_GTXTHRCFG_USBMaxTxBurstSize_MASK (0xff << 16)
+#define EXYNOS_USB3_GTXTHRCFG_USBMaxTxBurstSize_SHIFT 16
+#define EXYNOS_USB3_GTXTHRCFG_USBMaxTxBurstSize(_x) ((_x) << 16)
+
+#define EXYNOS_USB3_GRXTHRCFG 0xC10C
+#define EXYNOS_USB3_GRXTHRCFG_USBRxPktCntSel (1 << 29)
+#define EXYNOS_USB3_GRXTHRCFG_USBRxPktCnt_MASK (0xf << 24)
+#define EXYNOS_USB3_GRXTHRCFG_USBRxPktCnt_SHIFT 24
+#define EXYNOS_USB3_GRXTHRCFG_USBRxPktCnt(_x) ((_x) << 24)
+#define EXYNOS_USB3_GRXTHRCFG_USBMaxRxBurstSize_MASK (0x1f << 19)
+#define EXYNOS_USB3_GRXTHRCFG_USBMaxRxBurstSize_SHIFT 19
+#define EXYNOS_USB3_GRXTHRCFG_USBMaxRxBurstSize(_x) ((_x) << 19)
+
+#define EXYNOS_USB3_GCTL 0xC110
+#define EXYNOS_USB3_GCTL_PwrDnScale_MASK (0x1fff << 19)
+#define EXYNOS_USB3_GCTL_PwrDnScale_SHIFT 19
+#define EXYNOS_USB3_GCTL_PwrDnScale(_x) ((_x) << 19)
+#define EXYNOS_USB3_GCTL_U2RSTECN (1 << 16)
+#define EXYNOS_USB3_GCTL_FRMSCLDWN_MASK (0x3 << 14)
+#define EXYNOS_USB3_GCTL_FRMSCLDWN_SHIFT 14
+#define EXYNOS_USB3_GCTL_FRMSCLDWN(_x) ((_x) << 14)
+#define EXYNOS_USB3_GCTL_PrtCapDir_MASK (0x3 << 12)
+#define EXYNOS_USB3_GCTL_PrtCapDir_SHIFT 12
+#define EXYNOS_USB3_GCTL_PrtCapDir(_x) ((_x) << 12)
+#define EXYNOS_USB3_GCTL_CoreSoftReset (1 << 11)
+#define EXYNOS_USB3_GCTL_LocalLpBkEn (1 << 10)
+#define EXYNOS_USB3_GCTL_LpbkEn (1 << 9)
+#define EXYNOS_USB3_GCTL_DebugAttach (1 << 8)
+#define EXYNOS_USB3_GCTL_RAMClkSel_MASK (0x3 << 6)
+#define EXYNOS_USB3_GCTL_RAMClkSel_SHIFT 6
+#define EXYNOS_USB3_GCTL_RAMClkSel(_x) ((_x) << 6)
+#define EXYNOS_USB3_GCTL_ScaleDown_MASK (0x3 << 4)
+#define EXYNOS_USB3_GCTL_ScaleDown_SHIFT 4
+#define EXYNOS_USB3_GCTL_ScaleDown(_x) ((_x) << 4)
+#define EXYNOS_USB3_GCTL_DisScramble (1 << 3)
+#define EXYNOS_USB3_GCTL_SsPwrClmp (1 << 2)
+#define EXYNOS_USB3_GCTL_HsFsLsPwrClmp (1 << 1)
+#define EXYNOS_USB3_GCTL_DsblClkGtng (1 << 0)
+
+#define EXYNOS_USB3_GEVTEN 0xC114
+#define EXYNOS_USB3_GEVTEN_I2CEvtEn (1 << 1)
+#define EXYNOS_USB3_GEVTEN_ULPICKEvtEn (1 << 0)
+#define EXYNOS_USB3_GEVTEN_I2CCKEvtEn (1 << 0)
+
+#define EXYNOS_USB3_GSTS 0xC118
+#define EXYNOS_USB3_GSTS_CBELT_MASK (0xfff << 20)
+#define EXYNOS_USB3_GSTS_CBELT_SHIFT 20
+#define EXYNOS_USB3_GSTS_CBELT(_x) ((_x) << 20)
+#define EXYNOS_USB3_GSTS_OTG_IP (1 << 10)
+#define EXYNOS_USB3_GSTS_BC_IP (1 << 9)
+#define EXYNOS_USB3_GSTS_ADP_IP (1 << 8)
+#define EXYNOS_USB3_GSTS_Host_IP (1 << 7)
+#define EXYNOS_USB3_GSTS_Device_IP (1 << 6)
+#define EXYNOS_USB3_GSTS_CSRTimeout (1 << 5)
+#define EXYNOS_USB3_GSTS_BusErrAddrVld (1 << 4)
+#define EXYNOS_USB3_GSTS_CurMod_MASK (0x3 << 0)
+#define EXYNOS_USB3_GSTS_CurMod_SHIFT 0
+#define EXYNOS_USB3_GSTS_CurMod(_x) ((_x) << 0)
+
+#define EXYNOS_USB3_GSNPSID 0xC120
+
+#define EXYNOS_USB3_GGPIO 0xC124
+#define EXYNOS_USB3_GGPIO_GPO_MASK (0xffff << 16)
+#define EXYNOS_USB3_GGPIO_GPO_SHIFT 16
+#define EXYNOS_USB3_GGPIO_GPO(_x) ((_x) << 16)
+#define EXYNOS_USB3_GGPIO_GPI_MASK (0xffff << 0)
+#define EXYNOS_USB3_GGPIO_GPI_SHIFT 0
+#define EXYNOS_USB3_GGPIO_GPI(_x) ((x) << 0)
+
+#define EXYNOS_USB3_GUID 0xC128
+
+#define EXYNOS_USB3_GUCTL 0xC12C
+#define EXYNOS_USB3_GUCTL_SprsCtrlTransEn (1 << 17)
+#define EXYNOS_USB3_GUCTL_ResBwHSEPS (1 << 16)
+#define EXYNOS_USB3_GUCTL_CMdevAddr (1 << 15)
+#define EXYNOS_USB3_GUCTL_USBHstInAutoRetryEn (1 << 14)
+#define EXYNOS_USB3_GUCTL_USBHstInMaxBurst_MASK (0x7 << 11)
+#define EXYNOS_USB3_GUCTL_USBHstInMaxBurst_SHIFT 11
+#define EXYNOS_USB3_GUCTL_USBHstInMaxBurst(_x) ((_x) << 11)
+#define EXYNOS_USB3_GUCTL_DTCT_MASK (0x3 << 9)
+#define EXYNOS_USB3_GUCTL_DTCT_SHIFT 9
+#define EXYNOS_USB3_GUCTL_DTCT(_x) ((_x) << 9)
+#define EXYNOS_USB3_GUCTL_DTFT_MASK (0x1ff << 0)
+#define EXYNOS_USB3_GUCTL_DTFT_SHIFT 0
+#define EXYNOS_USB3_GUCTL_DTFT(_x) ((_x) << 0)
+
+#define EXYNOS_USB3_GBUSERRADDR_31_0 0xC130
+#define EXYNOS_USB3_GBUSERRADDR_63_32 0xC134
+#define EXYNOS_USB3_GPRTBIMAP_31_0 0xC138
+#define EXYNOS_USB3_GPRTBIMAP_63_32 0xC13C
+
+#define EXYNOS_USB3_GHWPARAMS0 0xC140
+#define EXYNOS_USB3_GHWPARAMS1 0xC144
+#define EXYNOS_USB3_GHWPARAMS2 0xC148
+#define EXYNOS_USB3_GHWPARAMS3 0xC14C
+#define EXYNOS_USB3_GHWPARAMS4 0xC150
+#define EXYNOS_USB3_GHWPARAMS5 0xC154
+#define EXYNOS_USB3_GHWPARAMS6 0xC158
+#define EXYNOS_USB3_GHWPARAMS7 0xC15C
+
+#define EXYNOS_USB3_GDBGFIFOSPACE 0xC160
+#define EXYNOS_USB3_GDBGLTSSM 0xC164
+
+#define EXYNOS_USB3_GDBGLSPMUX 0xC170
+#define EXYNOS_USB3_GDBGLSP 0xC174
+#define EXYNOS_USB3_GDBGEPINFO0 0xC178
+#define EXYNOS_USB3_GDBGEPINFO1 0xC17C
+
+#define EXYNOS_USB3_GPRTBIMAP_HS_31_0 0xC180
+#define EXYNOS_USB3_GPRTBIMAP_HS_63_32 0xC184
+#define EXYNOS_USB3_GPRTBIMAP_FS_31_0 0xC188
+#define EXYNOS_USB3_GPRTBIMAP_FS_63_32 0xC18C
+
+#define EXYNOS_USB3_GUSB2PHYCFG(_a) (0xC200 + ((_a) * 0x04))
+#define EXYNOS_USB3_GUSB2PHYCFGx_PHYSoftRst (1 << 31)
+#define EXYNOS_USB3_GUSB2PHYCFGx_PhyIntrNum_MASK (0x3f << 19)
+#define EXYNOS_USB3_GUSB2PHYCFGx_PhyIntrNum_SHIFT 19
+#define EXYNOS_USB3_GUSB2PHYCFGx_PhyIntrNum(_x) ((_x) << 19)
+#define EXYNOS_USB3_GUSB2PHYCFGx_ULPIExtVbusIndicator (1 << 18)
+#define EXYNOS_USB3_GUSB2PHYCFGx_ULPIExtVbusDrv (1 << 17)
+#define EXYNOS_USB3_GUSB2PHYCFGx_ULPIClkSusM (1 << 16)
+#define EXYNOS_USB3_GUSB2PHYCFGx_ULPIAutoRes (1 << 15)
+#define EXYNOS_USB3_GUSB2PHYCFGx_PhyLPwrClkSel (1 << 14)
+#define EXYNOS_USB3_GUSB2PHYCFGx_USBTrdTim_MASK (0xf << 10)
+#define EXYNOS_USB3_GUSB2PHYCFGx_USBTrdTim_SHIFT 10
+#define EXYNOS_USB3_GUSB2PHYCFGx_USBTrdTim(_x) ((_x) << 10)
+#define EXYNOS_USB3_GUSB2PHYCFGx_EnblSlpM (1 << 8)
+#define EXYNOS_USB3_GUSB2PHYCFGx_PHYSel (1 << 7)
+#define EXYNOS_USB3_GUSB2PHYCFGx_SusPHY (1 << 6)
+#define EXYNOS_USB3_GUSB2PHYCFGx_FSIntf (1 << 5)
+#define EXYNOS_USB3_GUSB2PHYCFGx_ULPI_UTMI_Sel (1 << 4)
+#define EXYNOS_USB3_GUSB2PHYCFGx_PHYIf (1 << 3)
+#define EXYNOS_USB3_GUSB2PHYCFGx_TOutCal_MASK (0x7 << 0)
+#define EXYNOS_USB3_GUSB2PHYCFGx_TOutCal_SHIFT 0
+#define EXYNOS_USB3_GUSB2PHYCFGx_TOutCal(_x) ((_x) << 0)
+
+#define EXYNOS_USB3_GUSB2I2CCTL(_a) (0xC240 + ((_a) * 0x04))
+
+#define EXYNOS_USB3_GUSB2PHYACC(_a) (0xC280 + ((_a) * 0x04))
+#define EXYNOS_USB3_GUSB2PHYACCx_DisUlpiDrvr (1 << 26)
+#define EXYNOS_USB3_GUSB2PHYACCx_NewRegReq (1 << 25)
+#define EXYNOS_USB3_GUSB2PHYACCx_VStsDone (1 << 24)
+#define EXYNOS_USB3_GUSB2PHYACCx_VStsBsy (1 << 23)
+#define EXYNOS_USB3_GUSB2PHYACCx_RegWr (1 << 22)
+#define EXYNOS_USB3_GUSB2PHYACCx_RegAddr_MASK (0x3f << 16)
+#define EXYNOS_USB3_GUSB2PHYACCx_RegAddr_SHIFT 16
+#define EXYNOS_USB3_GUSB2PHYACCx_RegAddr(_x) ((_x) << 16)
+/* Next 2 fields are overlaping. Is it error in user manual? */
+#define EXYNOS_USB3_GUSB2PHYACCx_VCtrl_MASK (0xff << 8)
+#define EXYNOS_USB3_GUSB2PHYACCx_VCtrl_SHIFT 8
+#define EXYNOS_USB3_GUSB2PHYACCx_VCtrl(_x) ((_x) << 8)
+/*--------*/
+#define EXYNOS_USB3_GUSB2PHYACCx_ExtRegAddr_MASK (0x3f << 8)
+#define EXYNOS_USB3_GUSB2PHYACCx_ExtRegAddr_SHIFT 8
+#define EXYNOS_USB3_GUSB2PHYACCx_ExtRegAddr(_x) ((_x) << 8)
+/*--------*/
+#define EXYNOS_USB3_GUSB2PHYACCx_RegData_MASK (0xff << 0)
+#define EXYNOS_USB3_GUSB2PHYACCx_RegData_SHIFT 0
+#define EXYNOS_USB3_GUSB2PHYACCx_RegData(_x) ((_x) << 0)
+
+#define EXYNOS_USB3_GUSB3PIPECTL(_a) (0xC2C0 + ((_a) * 0x04))
+#define EXYNOS_USB3_GUSB3PIPECTLx_PHYSoftRst (1 << 31)
+#define EXYNOS_USB3_GUSB3PIPECTLx_request_p1p2p3 (1 << 24)
+#define EXYNOS_USB3_GUSB3PIPECTLx_StartRxdetU3RxDet (1 << 23)
+#define EXYNOS_USB3_GUSB3PIPECTLx_DisRxDetU3RxDet (1 << 22)
+#define EXYNOS_USB3_GUSB3PIPECTLx_delay_p1p2p3_MASK (0x7 << 19)
+#define EXYNOS_USB3_GUSB3PIPECTLx_delay_p1p2p3_SHIFT 19
+#define EXYNOS_USB3_GUSB3PIPECTLx_delay_p1p2p3(_x) ((_x) << 19)
+#define EXYNOS_USB3_GUSB3PIPECTLx_delay_phy_pwr_p1p2p3 (1 << 18)
+#define EXYNOS_USB3_GUSB3PIPECTLx_SuspSSPhy (1 << 17)
+#define EXYNOS_USB3_GUSB3PIPECTLx_DatWidth_MASK (0x3 << 15)
+#define EXYNOS_USB3_GUSB3PIPECTLx_DatWidth_SHIFT 15
+#define EXYNOS_USB3_GUSB3PIPECTLx_DatWidth(_x) ((_x) << 15)
+#define EXYNOS_USB3_GUSB3PIPECTLx_AbortRxDetInU2 (1 << 14)
+#define EXYNOS_USB3_GUSB3PIPECTLx_SkipRxDet (1 << 13)
+#define EXYNOS_USB3_GUSB3PIPECTLx_LFPSP0Algn (1 << 12)
+#define EXYNOS_USB3_GUSB3PIPECTLx_P3P2TranOK (1 << 11)
+#define EXYNOS_USB3_GUSB3PIPECTLx_LFPSFilt (1 << 9)
+#define EXYNOS_USB3_GUSB3PIPECTLx_TxSwing (1 << 6)
+#define EXYNOS_USB3_GUSB3PIPECTLx_TxMargin_MASK (0x7 << 3)
+#define EXYNOS_USB3_GUSB3PIPECTLx_TxMargin_SHIFT 3
+#define EXYNOS_USB3_GUSB3PIPECTLx_TxMargin(_x) ((_x) << 3)
+#define EXYNOS_USB3_GUSB3PIPECTLx_TxDeemphasis_MASK (0x3 << 1)
+#define EXYNOS_USB3_GUSB3PIPECTLx_TxDeemphasis_SHIFT 1
+#define EXYNOS_USB3_GUSB3PIPECTLx_TxDeemphasis(_x) ((_x) << 1)
+#define EXYNOS_USB3_GUSB3PIPECTLx_ElasticBufferMode (1 << 0)
+
+#define EXYNOS_USB3_GTXFIFOSIZ(_a) (0xC300 + ((_a) * 0x04))
+#define EXYNOS_USB3_GTXFIFOSIZx_TxFStAddr_n_MASK (0xffff << 16)
+#define EXYNOS_USB3_GTXFIFOSIZx_TxFStAddr_n_SHIFT 16
+#define EXYNOS_USB3_GTXFIFOSIZx_TxFStAddr_n(_x) ((_x) << 16)
+#define EXYNOS_USB3_GTXFIFOSIZx_TxFDep_n_MASK (0xffff << 0)
+#define EXYNOS_USB3_GTXFIFOSIZx_TxFDep_n_SHIFT 0
+#define EXYNOS_USB3_GTXFIFOSIZx_TxFDep_n(_x) ((_x) << 0)
+
+#define EXYNOS_USB3_GRXFIFOSIZ(_a) (0xC380 + ((_a) * 0x04))
+#define EXYNOS_USB3_GRXFIFOSIZx_RxFStAddr_n_MASK (0xffff << 16)
+#define EXYNOS_USB3_GRXFIFOSIZx_RxFStAddr_n_SHIFT 16
+#define EXYNOS_USB3_GRXFIFOSIZx_RxFStAddr_n(_x) ((_x) << 16)
+#define EXYNOS_USB3_GRXFIFOSIZx_RxFDep_n_MASK (0xffff << 0)
+#define EXYNOS_USB3_GRXFIFOSIZx_RxFDep_n_SHIFT 0
+#define EXYNOS_USB3_GRXFIFOSIZx_RxFDep_n(_x) ((_x) << 0)
+
+#define EXYNOS_USB3_GEVNTADR_31_0(_a) (0xC400 + ((_a) * 0x10))
+#define EXYNOS_USB3_GEVNTADR_63_32(_a) (0xC404 + ((_a) * 0x10))
+
+#define EXYNOS_USB3_GEVNTSIZ(_a) (0xC408 + ((_a) * 0x10))
+#define EXYNOS_USB3_GEVNTSIZx_EvntIntMask (1 << 31)
+#define EXYNOS_USB3_GEVNTSIZx_EVNTSiz_MASK (0xffff << 0)
+#define EXYNOS_USB3_GEVNTSIZx_EVNTSiz_SHIFT 0
+#define EXYNOS_USB3_GEVNTSIZx_EVNTSiz(x) ((_x) << 0)
+
+#define EXYNOS_USB3_GEVNTCOUNT(_a) (0xC40C + ((_a) * 0x10))
+#define EXYNOS_USB3_GEVNTCOUNTx_EVNTCount_MASK (0xffff << 0)
+#define EXYNOS_USB3_GEVNTCOUNTx_EVNTCount_SHIFT 0
+#define EXYNOS_USB3_GEVNTCOUNTx_EVNTCount(_x) ((_x) << 0)
+
+/* Event Buffer Content for Device Endpoint-Specific Events (DEPEVT) */
+#define EXYNOS_USB3_DEPEVT_EventParam_MASK (0xffff << 16)
+#define EXYNOS_USB3_DEPEVT_EventParam_SHIFT 16
+#define EXYNOS_USB3_DEPEVT_EventParam(_x) ((_x) << 16)
+#define EXYNOS_USB3_DEPEVT_EventStatus_MASK (0xf << 12)
+#define EXYNOS_USB3_DEPEVT_EventStatus_SHIFT 12
+#define EXYNOS_USB3_DEPEVT_EventStatus_CTL_MASK (0x3 << 12)
+#define EXYNOS_USB3_DEPEVT_EventStatus_CTL_SETUP (0 << 12)
+#define EXYNOS_USB3_DEPEVT_EventStatus_CTL_DATA (1 << 12)
+#define EXYNOS_USB3_DEPEVT_EventStatus_CTL_STATUS (2 << 12)
+#define EXYNOS_USB3_DEPEVT_EventStatus_BUSERR (1 << 12)
+#define EXYNOS_USB3_DEPEVT_EVENT_MASK (0xf << 6)
+#define EXYNOS_USB3_DEPEVT_EVENT_SHIFT 6
+#define EXYNOS_USB3_DEPEVT_EVENT_EPCmdCmplt (7 << 6)
+#define EXYNOS_USB3_DEPEVT_EVENT_StreamEvt (6 << 6)
+#define EXYNOS_USB3_DEPEVT_EVENT_RxTxfifoEvt (4 << 6)
+#define EXYNOS_USB3_DEPEVT_EVENT_XferNotReady (3 << 6)
+#define EXYNOS_USB3_DEPEVT_EVENT_XferInProgress (2 << 6)
+#define EXYNOS_USB3_DEPEVT_EVENT_XferComplete (1 << 6)
+#define EXYNOS_USB3_DEPEVT_EPNUM_MASK (0x1f << 1)
+#define EXYNOS_USB3_DEPEVT_EPNUM_SHIFT 1
+#define EXYNOS_USB3_DEPEVT_EPNUM(_x) ((_x) << 1)
+
+/* Event Buffer Content for Device-Specific Events (DEVT) */
+#define EXYNOS_USB3_DEVT_EventParam_MASK (0xf << 16)
+#define EXYNOS_USB3_DEVT_EventParam_SHIFT 16
+#define EXYNOS_USB3_DEVT_EventParam_SS (1 << 20)
+#define EXYNOS_USB3_DEVT_EventParam(_x) ((_x) << 16)
+#define EXYNOS_USB3_DEVT_EVENT_MASK (0xf << 8)
+#define EXYNOS_USB3_DEVT_EVENT_SHIFT 8
+#define EXYNOS_USB3_DEVT_EVENT_VndrDevTstRcved (12 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_EvntOverflow (11 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_CmdCmplt (10 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_ErrticErr (9 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_Sof (7 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_EOPF (6 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_WkUpEvt (4 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_ULStChng (3 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_ConnectDone (2 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_USBRst (1 << 8)
+#define EXYNOS_USB3_DEVT_EVENT_DisconnEvt (0 << 8)
+
+#define EXYNOS_USB3_GHWPARAMS8 0xC600
+
+/* USB 2.0 OTG and Battery Charger registers */
+#define EXYNOS_USB3_OCFG 0xCC00
+#define EXYNOS_USB3_OCFG_OTG_Version (1 << 2)
+#define EXYNOS_USB3_OCFG_HNPCap (1 << 1)
+#define EXYNOS_USB3_OCFG_SRPCap (1 << 0)
+
+#define EXYNOS_USB3_OCTL 0xCC04
+#define EXYNOS_USB3_OCTL_PeriMode (1 << 6)
+#define EXYNOS_USB3_OCTL_PrtPwrCtl (1 << 5)
+#define EXYNOS_USB3_OCTL_HNPReq (1 << 4)
+#define EXYNOS_USB3_OCTL_SesReq (1 << 3)
+#define EXYNOS_USB3_OCTL_TermSelDLPulse (1 << 2)
+#define EXYNOS_USB3_OCTL_DevSetHNPEn (1 << 1)
+#define EXYNOS_USB3_OCTL_HstSetHNPEn (1 << 0)
+
+#define EXYNOS_USB3_OEVT 0xCC08
+#define EXYNOS_USB3_OEVT_DeviceMode (1 << 31)
+#define EXYNOS_USB3_OEVT_OTGConIDStsChngEvnt (1 << 24)
+#define EXYNOS_USB3_OEVT_OTGADevBHostEndEvnt (1 << 20)
+#define EXYNOS_USB3_OEVT_OTGADevHostEvnt (1 << 19)
+#define EXYNOS_USB3_OEVT_OTGADevHNPChngEvnt (1 << 18)
+#define EXYNOS_USB3_OEVT_OTGADevSRPDetEvnt (1 << 17)
+#define EXYNOS_USB3_OEVT_OTGADevSessEndDetEvnt (1 << 16)
+#define EXYNOS_USB3_OEVT_OTGBDevBHostEndEvnt (1 << 11)
+#define EXYNOS_USB3_OEVT_OTGBDevHNPChngEvnt (1 << 10)
+#define EXYNOS_USB3_OEVT_OTGBDevSessVldDetEvnt (1 << 9)
+#define EXYNOS_USB3_OEVT_OTGBDevVBUSChngEvnt (1 << 8)
+#define EXYNOS_USB3_OEVT_BSesVld (1 << 3)
+#define EXYNOS_USB3_OEVT_HstNegSts (1 << 2)
+#define EXYNOS_USB3_OEVT_SesReqSts (1 << 1)
+#define EXYNOS_USB3_OEVT_OEVTError (1 << 0)
+
+#define EXYNOS_USB3_OEVTEN 0xCC0C
+#define EXYNOS_USB3_OEVTEN_OTGConIDStsChngEvntEn (1 << 24)
+#define EXYNOS_USB3_OEVTEN_OTGADevBHostEndEvntEn (1 << 20)
+#define EXYNOS_USB3_OEVTEN_OTGADevHostEvntEn (1 << 19)
+#define EXYNOS_USB3_OEVTEN_OTGADevHNPChngEvntEn (1 << 18)
+#define EXYNOS_USB3_OEVTEN_OTGADevSRPDetEvntEn (1 << 17)
+#define EXYNOS_USB3_OEVTEN_OTGADevSessEndDetEvntEn (1 << 16)
+#define EXYNOS_USB3_OEVTEN_OTGBDevBHostEndEvntEn (1 << 11)
+#define EXYNOS_USB3_OEVTEN_OTGBDevHNPChngEvntEn (1 << 10)
+#define EXYNOS_USB3_OEVTEN_OTGBDevSessVldDetEvntEn (1 << 9)
+#define EXYNOS_USB3_OEVTEN_OTGBDevVBUSChngEvntEn (1 << 8)
+
+#define EXYNOS_USB3_OSTS 0xCC10
+#define EXYNOS_USB3_OSTS_OTG_state_MASK (0xf << 8)
+#define EXYNOS_USB3_OSTS_OTG_state_SHIFT 8
+#define EXYNOS_USB3_OSTS_OTG_state(_x) ((_x) << 8)
+#define EXYNOS_USB3_OSTS_PeripheralState (1 << 4)
+#define EXYNOS_USB3_OSTS_xHCIPrtPower (1 << 3)
+#define EXYNOS_USB3_OSTS_BSesVld (1 << 2)
+#define EXYNOS_USB3_OSTS_VbusVld (1 << 1)
+#define EXYNOS_USB3_OSTS_ConIDSts (1 << 0)
+
+#define EXYNOS_USB3_ADPCFG 0xCC20
+#define EXYNOS_USB3_ADPCFG_PrbPer_MASK (0x3 << 30)
+#define EXYNOS_USB3_ADPCFG_PrbPer_SHIFT 30
+#define EXYNOS_USB3_ADPCFG_PrbPer(_x) ((_x) << 30)
+#define EXYNOS_USB3_ADPCFG_PrbDelta_MASK (0x3 << 28)
+#define EXYNOS_USB3_ADPCFG_PrbDelta_SHIFT 28
+#define EXYNOS_USB3_ADPCFG_PrbDelta(_x) ((_x) << 28)
+#define EXYNOS_USB3_ADPCFG_PrbDschg_MASK (0x3 << 26)
+#define EXYNOS_USB3_ADPCFG_PrbDschg_SHIFT 26
+#define EXYNOS_USB3_ADPCFG_PrbDschg(_x) ((_x) << 26)
+
+#define EXYNOS_USB3_ADPCTL 0xCC24
+#define EXYNOS_USB3_ADPCTL_EnaPrb (1 << 28)
+#define EXYNOS_USB3_ADPCTL_EnaSns (1 << 27)
+#define EXYNOS_USB3_ADPCTL_ADPEn (1 << 26)
+#define EXYNOS_USB3_ADPCTL_ADPRes (1 << 25)
+#define EXYNOS_USB3_ADPCTL_WB (1 << 24)
+
+#define EXYNOS_USB3_ADPEVT 0xCC28
+#define EXYNOS_USB3_ADPEVT_AdpPrbEvnt (1 << 28)
+#define EXYNOS_USB3_ADPEVT_AdpSnsEvnt (1 << 27)
+#define EXYNOS_USB3_ADPEVT_AdpTmoutEvnt (1 << 26)
+#define EXYNOS_USB3_ADPEVT_ADPRstCmpltEvnt (1 << 25)
+#define EXYNOS_USB3_ADPEVT_RTIM_MASK (0x7ff << 0)
+#define EXYNOS_USB3_ADPEVT_RTIM_SHIFT 0
+#define EXYNOS_USB3_ADPEVT_RTIM(_x) ((_x) << 0)
+
+#define EXYNOS_USB3_ADPEVTEN 0xCC2C
+#define EXYNOS_USB3_ADPEVTEN_AdpPrbEvntEn (1 << 28)
+#define EXYNOS_USB3_ADPEVTEN_AdpSnsEvntEn (1 << 27)
+#define EXYNOS_USB3_ADPEVTEN_AdpTmoutEvntEn (1 << 26)
+#define EXYNOS_USB3_ADPEVTEN_ADPRstCmpltEvntEn (1 << 25)
+
+#define EXYNOS_USB3_BCFG 0xCC30
+#define EXYNOS_USB3_BCFG_IDDIG_SEL (1 << 1)
+#define EXYNOS_USB3_BCFG_CHIRP_EN (1 << 0)
+
+#define EXYNOS_USB3_BCEVT 0xCC38
+#define EXYNOS_USB3_BCEVT_MV_ChngEvnt (1 << 24)
+#define EXYNOS_USB3_BCEVT_MultValIdBc_MASK (0x1f << 0)
+#define EXYNOS_USB3_BCEVT_MultValIdBc_SHIFT 0
+#define EXYNOS_USB3_BCEVT_MultValIdBc(_x) ((_x) << 0)
+
+#define EXYNOS_USB3_BCEVTEN 0xCC3C
+#define EXYNOS_USB3_BCEVTEN_MV_ChngEvntEn (1 << 24)
+
+#endif /* __LINUX_USB_EXYNOS_USB3_DRD_H */
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB3Phy.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB3Phy.h
new file mode 100644
index 000000000..f903e0cdc
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/Exynos5_USB3Phy.h
@@ -0,0 +1,80 @@
+#ifndef _EFI_EXYNOS5_USB3_PHY_H_
+#define _EFI_EXYNOS5_USB3_PHY_H_
+
+#define EXYNOS5_USB3_PHY_HOST_CTRL0 0x12100000
+
+#define EXYNOS_USB3_LINKSYSTEM (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x04)
+#define EXYNOS_USB3_PHYUTMI (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x08)
+#define EXYNOS_USB3_PHYPIPE (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x0C)
+#define EXYNOS_USB3_PHYCLKRST (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x10)
+#define EXYNOS_USB3_PHYREG0 (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x14)
+#define EXYNOS_USB3_PHYREG1 (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x18)
+#define EXYNOS_USB3_PHYPARAM0 (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x1C)
+#define EXYNOS_USB3_PHYPARAM1 (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x20)
+#define EXYNOS_USB3_PHYTERM (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x24)
+#define EXYNOS_USB3_PHYTEST (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x28)
+#define EXYNOS_USB3_PHYADP (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x2C)
+#define EXYNOS_USB3_PHYBATCHG (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x30)
+#define EXYNOS_USB3_PHYRESUME (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x34)
+#define EXYNOS_USB3_LINKPORT (EXYNOS5_USB3_PHY_HOST_CTRL0 + 0x44)
+
+
+#define EXYNOS_USB3_PHYUTMI_OTGDISABLE (1 << 6)
+#define EXYNOS_USB3_PHYUTMI_FORCESUSPEND (1 << 1)
+#define EXYNOS_USB3_PHYUTMI_FORCESLEEP (1 << 0)
+
+#define EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL_MASK (0xff << 23)
+#define EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL_SHIFT (23)
+#define EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL_LIMIT (0xff)
+#define EXYNOS_USB3_PHYCLKRST_SSC_REF_CLK_SEL(_x) ((_x) << 23)
+
+#define EXYNOS_USB3_PHYCLKRST_SSC_RANGE_MASK (0x03 << 21)
+#define EXYNOS_USB3_PHYCLKRST_SSC_RANGE_SHIFT (21)
+#define EXYNOS_USB3_PHYCLKRST_SSC_RANGE_LIMIT (0x03)
+#define EXYNOS_USB3_PHYCLKRST_SSC_RANGE(_x) ((_x) << 21)
+
+#define EXYNOS_USB3_PHYCLKRST_SSC_EN (1 << 20)
+#define EXYNOS_USB3_PHYCLKRST_REF_SSP_EN (1 << 19)
+#define EXYNOS_USB3_PHYCLKRST_REF_CLKDIV2 (1 << 18)
+
+#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11)
+#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER_SHIFT (11)
+#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER_LIMIT (0x7f)
+#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER(_x) ((_x) << 11)
+
+#define EXYNOS_USB3_PHYCLKRST_SSC_EN (1 << 20)
+#define EXYNOS_USB3_PHYCLKRST_REF_SSP_EN (1 << 19)
+#define EXYNOS_USB3_PHYCLKRST_REF_CLKDIV2 (1 << 18)
+
+#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11)
+#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER_SHIFT (11)
+#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER_LIMIT (0x7f)
+#define EXYNOS_USB3_PHYCLKRST_MPLL_MULTIPLIER(_x) ((_x) << 11)
+
+#define EXYNOS_USB3_PHYCLKRST_FSEL_MASK (0x3f << 5)
+#define EXYNOS_USB3_PHYCLKRST_FSEL_SHIFT (5)
+#define EXYNOS_USB3_PHYCLKRST_FSEL_LIMIT (0x3f)
+#define EXYNOS_USB3_PHYCLKRST_FSEL(_x) ((_x) << 5)
+
+#define EXYNOS_USB3_PHYCLKRST_RETENABLEN (1 << 4)
+
+#define EXYNOS_USB3_PHYCLKRST_REFCLKSEL_MASK (0x03 << 2)
+#define EXYNOS_USB3_PHYCLKRST_REFCLKSEL_SHIFT (2)
+#define EXYNOS_USB3_PHYCLKRST_REFCLKSEL_LIMIT (0x03)
+#define EXYNOS_USB3_PHYCLKRST_REFCLKSEL(_x) ((_x) << 2)
+
+#define EXYNOS_USB3_PHYCLKRST_PORTRESET (1 << 1)
+#define EXYNOS_USB3_PHYCLKRST_COMMONONN (1 << 0)
+
+
+//-------------------------------------------------------
+// Functions
+//-------------------------------------------------------
+
+void exynos5_usb_phy30_init(void);
+void exynos_xhci_phy_set(void);
+UINT32 exynos_xhci_change_mode(void);
+
+#endif
+
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.c
new file mode 100644
index 000000000..a4295cc85
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.c
@@ -0,0 +1,684 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ 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 "PciEmulation.h"
+#include "Exynos5_USB2Phy.h"
+#include "Exynos5_USB3Phy.h"
+#include "Exynos5_USB3Drd.h"
+
+#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
+#define USBDRD_CONTROLLER_OPERATION_REG_SIZE 0x400
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ PCI_DEVICE_PATH PciDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_IO_DEVICE_PATH;
+
+typedef struct {
+ UINT32 Signature;
+ EFI_PCI_IO_DEVICE_PATH DevicePath;
+ EFI_PCI_IO_PROTOCOL PciIoProtocol;
+ PCI_TYPE00 *ConfigSpace;
+ PCI_ROOT_BRIDGE RootBridge;
+ UINTN Segment;
+} EFI_PCI_IO_PRIVATE_DATA;
+
+#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
+#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
+
+EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplateUSB2 =
+{
+ {
+ { ACPI_DEVICE_PATH, ACPI_DP, sizeof (ACPI_HID_DEVICE_PATH), 0},
+ EISA_PNP_ID(0x0A03), // HID
+ 0 // UID
+ },
+ {
+ { HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (PCI_DEVICE_PATH), 0},
+ 0,
+ 0
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
+};
+
+EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplateUSB3 =
+{
+ {
+ { ACPI_DEVICE_PATH, ACPI_DP, sizeof (ACPI_HID_DEVICE_PATH), 0},
+ EISA_PNP_ID(0x0A03), // HID
+ 1 // UID
+ },
+ {
+ { HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (PCI_DEVICE_PATH), 0},
+ 0,
+ 1
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
+};
+
+EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplateUSB1 =
+{
+ {
+ { ACPI_DEVICE_PATH, ACPI_DP, sizeof (ACPI_HID_DEVICE_PATH), 0},
+ EISA_PNP_ID(0x0A03), // HID
+ 2 // UID
+ },
+ {
+ { HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (PCI_DEVICE_PATH), 0},
+ 0,
+ 2
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
+};
+
+
+STATIC
+VOID
+ConfigureUSBHost (
+ VOID
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __func__, __LINE__));
+
+ exynos5_usb_phy20_init();
+#if defined(XHCI_SUPPORT)
+ exynos5_usb_phy30_init();
+ exynos_xhci_change_mode();
+ exynos_xhci_phy_set();
+#endif
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+}
+
+
+EFI_STATUS
+PciIoPollMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoPollIo (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoMemRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
+
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return PciRootBridgeIoMemRead (&Private->RootBridge.Io,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
+ Count,
+ Buffer
+ );
+}
+
+EFI_STATUS
+PciIoMemWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
+
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
+ Count,
+ Buffer
+ );
+}
+
+EFI_STATUS
+PciIoIoRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoPciRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
+
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
+ Count,
+ TRUE,
+ (PTR)(UINTN)Buffer,
+ TRUE,
+ (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset)
+ );
+}
+
+EFI_STATUS
+PciIoPciWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
+
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Count,
+ TRUE,
+ (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset),
+ TRUE,
+ (PTR)(UINTN)Buffer
+ );
+}
+
+EFI_STATUS
+PciIoCopyMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 DestBarIndex,
+ IN UINT64 DestOffset,
+ IN UINT8 SrcBarIndex,
+ IN UINT64 SrcOffset,
+ IN UINTN Count
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ DMA_MAP_OPERATION DmaOperation;
+
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ if (Operation == EfiPciIoOperationBusMasterRead) {
+ DmaOperation = MapOperationBusMasterRead;
+ } else if (Operation == EfiPciIoOperationBusMasterWrite) {
+ DmaOperation = MapOperationBusMasterWrite;
+ } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
+ DmaOperation = MapOperationBusMasterCommonBuffer;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
+}
+
+EFI_STATUS
+PciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return DmaUnmap (Mapping);
+}
+
+EFI_STATUS
+PciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
+ // Check this
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
+}
+
+
+EFI_STATUS
+PciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return DmaFreeBuffer (Pages, HostAddress);
+}
+
+
+EFI_STATUS
+PciIoFlush (
+ IN EFI_PCI_IO_PROTOCOL *This
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoGetLocation (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *SegmentNumber,
+ OUT UINTN *BusNumber,
+ OUT UINTN *DeviceNumber,
+ OUT UINTN *FunctionNumber
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
+
+ if (SegmentNumber != NULL) {
+ *SegmentNumber = Private->Segment;
+ }
+
+ if (BusNumber != NULL) {
+ *BusNumber = 0xff;
+ }
+
+ if (DeviceNumber != NULL) {
+ *DeviceNumber = 0;
+ }
+
+ if (FunctionNumber != NULL) {
+ *FunctionNumber = 0;
+ }
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __FUNCTION__, __LINE__));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL
+ )
+{
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __FUNCTION__, __LINE__));
+ switch (Operation) {
+ case EfiPciIoAttributeOperationGet:
+ case EfiPciIoAttributeOperationSupported:
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ // We are not a real PCI device so just say things we kind of do
+ *Result = EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_DEVICE_ENABLE;
+ break;
+
+ case EfiPciIoAttributeOperationSet:
+ case EfiPciIoAttributeOperationEnable:
+ case EfiPciIoAttributeOperationDisable:
+ // Since we are not a real PCI device no enable/set or disable operations exist.
+ DEBUG((EFI_D_INFO, "--%a(Set:1, Enable:2, Disable:3)(%d):%d\n", __FUNCTION__, Operation,__LINE__));
+ return EFI_SUCCESS;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ };
+ DEBUG((EFI_D_INFO, "--%a(Get:0, Supported:4)(%d):%d\n", __FUNCTION__, Operation,__LINE__));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoGetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports, OPTIONAL
+ OUT VOID **Resources OPTIONAL
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+PciIoSetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+EFI_PCI_IO_PROTOCOL PciIoTemplate =
+{
+ PciIoPollMem,
+ PciIoPollIo,
+ PciIoMemRead,
+ PciIoMemWrite,
+ PciIoIoRead,
+ PciIoIoWrite,
+ PciIoPciRead,
+ PciIoPciWrite,
+ PciIoCopyMem,
+ PciIoMap,
+ PciIoUnmap,
+ PciIoAllocateBuffer,
+ PciIoFreeBuffer,
+ PciIoFlush,
+ PciIoGetLocation,
+ PciIoAttributes,
+ PciIoGetBarAttributes,
+ PciIoSetBarAttributes,
+ 0,
+ 0
+};
+
+EFI_STATUS
+EFIAPI
+PciEmulationEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE HandleUSB2;
+ EFI_PCI_IO_PRIVATE_DATA *PrivateUSB2;
+#if defined(OHCI_SUPPORT)
+ EFI_HANDLE HandleUSB1;
+ EFI_PCI_IO_PRIVATE_DATA *PrivateUSB1;
+#endif
+#if defined(XHCI_SUPPORT)
+ EFI_HANDLE HandleUSB3;
+ EFI_PCI_IO_PRIVATE_DATA *PrivateUSB3;
+#endif
+ UINT8 CapabilityLength;
+ UINT8 PhysicalPorts;
+#if defined(OHCI_SUPPORT)
+#else
+ UINTN Count;
+#endif
+
+ //Configure USB host for Exynos.
+ ConfigureUSBHost();
+
+ // Create a private structure for USB 2.0
+ PrivateUSB2 = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
+ if (PrivateUSB2 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+ PrivateUSB2->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
+ PrivateUSB2->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
+ PrivateUSB2->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base
+ PrivateUSB2->Segment = 0; // Default to segment zero
+
+
+#if defined(XHCI_SUPPORT)
+ // Create a private structure for USB 3.0
+ PrivateUSB3 = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
+ if (PrivateUSB3 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+ PrivateUSB3->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
+ PrivateUSB3->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
+ PrivateUSB3->RootBridge.MemoryStart = USB_XHCI_HCCAPBASE; // Get the USB capability register base
+ PrivateUSB3->Segment = 0; // Default to segment zero
+#endif
+
+#if defined(OHCI_SUPPORT)
+ // Create a private structure for USB 1.0
+ PrivateUSB1 = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
+ if (PrivateUSB1 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+ PrivateUSB1->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
+ PrivateUSB1->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
+ PrivateUSB1->RootBridge.MemoryStart = USB_OHCI_HCCAPBASE; // Get the USB capability register base
+ PrivateUSB1->Segment = 0; // Default to segment zero
+#endif
+
+ // USB 2.0
+ // Find out the capability register length and number of physical ports.
+ CapabilityLength = MmioRead8(PrivateUSB2->RootBridge.MemoryStart);
+ PhysicalPorts = (MmioRead32 (PrivateUSB2->RootBridge.MemoryStart + 0x4)) & 0x0000000F;
+
+ // Calculate the total size of the USB registers.
+ PrivateUSB2->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
+
+ // Enable Port Power bit in Port status and control registers in EHCI register space.
+ // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
+ // host controller implementation includes port power control.
+ for (Count = 0; Count < PhysicalPorts; Count++) {
+ MmioOr32 ((PrivateUSB2->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000);
+ }
+
+#if defined(XHCI_SUPPORT)
+ // USB 3.0
+ // Find out the capability register length and number of physical ports.
+ CapabilityLength = MmioRead8(PrivateUSB3->RootBridge.MemoryStart);
+ PhysicalPorts = ((MmioRead32 (PrivateUSB3->RootBridge.MemoryStart + 0x4)) & 0xFF000000) >> 24;
+
+ // Calculate the total size of the USB registers.
+ // 0x20 0x400 0x10
+ //Private->RootBridge.MemorySize = CapabilityLength + (USBDRD_CONTROLLER_OPERATION_REG_SIZE + (0x10 * (PhysicalPorts - 1)));
+ PrivateUSB3->RootBridge.MemorySize = 0x100000;
+
+ for (Count = 0; Count < PhysicalPorts; Count++) {
+ MmioOr32 (PrivateUSB3->RootBridge.MemoryStart + CapabilityLength + USBDRD_CONTROLLER_OPERATION_REG_SIZE + (0x10 * Count), 0x00000200);
+ }
+#endif
+
+#if defined(OHCI_SUPPORT)
+ CapabilityLength = 0;
+ PhysicalPorts = 3;
+ PrivateUSB1->RootBridge.MemorySize = 0x60;
+#endif
+
+
+ // USB 2.0
+ // Create fake PCI config space.
+ PrivateUSB2->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
+ if (PrivateUSB2->ConfigSpace == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ FreePool(PrivateUSB2);
+ return Status;
+ }
+
+ // Configure PCI config space
+ PrivateUSB2->ConfigSpace->Hdr.VendorId = 0x3530;
+ PrivateUSB2->ConfigSpace->Hdr.DeviceId = 0x3530;
+ PrivateUSB2->ConfigSpace->Hdr.ClassCode[0] = 0x20;
+ PrivateUSB2->ConfigSpace->Hdr.ClassCode[1] = 0x03;
+ PrivateUSB2->ConfigSpace->Hdr.ClassCode[2] = 0x0C;
+ PrivateUSB2->ConfigSpace->Device.Bar[0] = PrivateUSB2->RootBridge.MemoryStart;
+
+#if defined(XHCI_SUPPORT)
+ // USB 3.0
+ // Create fake PCI config space.
+ PrivateUSB3->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
+ if (PrivateUSB3->ConfigSpace == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ FreePool(PrivateUSB3);
+ return Status;
+ }
+
+ // Configure PCI config space
+ PrivateUSB3->ConfigSpace->Hdr.VendorId = 0x3530;
+ PrivateUSB3->ConfigSpace->Hdr.DeviceId = 0x3530;
+ PrivateUSB3->ConfigSpace->Hdr.ClassCode[0] = 0x30; /* 0x20 : EHIC, 0x30 : XHCI */
+ PrivateUSB3->ConfigSpace->Hdr.ClassCode[1] = 0x03;
+ PrivateUSB3->ConfigSpace->Hdr.ClassCode[2] = 0x0C;
+ PrivateUSB3->ConfigSpace->Device.Bar[0] = PrivateUSB3->RootBridge.MemoryStart;
+#endif
+
+#if defined(OHCI_SUPPORT)
+ // USB 1.0
+ // Create fake PCI config space.
+ PrivateUSB1->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
+ if (PrivateUSB1->ConfigSpace == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ FreePool(PrivateUSB1);
+ return Status;
+ }
+
+ // Configure PCI config space
+ PrivateUSB1->ConfigSpace->Hdr.VendorId = 0x3530;
+ PrivateUSB1->ConfigSpace->Hdr.DeviceId = 0x3530;
+ PrivateUSB1->ConfigSpace->Hdr.ClassCode[0] = 0x10;
+ PrivateUSB1->ConfigSpace->Hdr.ClassCode[1] = 0x03;
+ PrivateUSB1->ConfigSpace->Hdr.ClassCode[2] = 0x0C;
+ PrivateUSB1->ConfigSpace->Device.Bar[0] = PrivateUSB2->RootBridge.MemoryStart;
+#endif
+
+
+ HandleUSB2 = NULL;
+
+ // USB 2.0
+ // Unique device path.
+ CopyMem(&PrivateUSB2->DevicePath, &PciIoDevicePathTemplateUSB2, sizeof(PciIoDevicePathTemplateUSB2));
+ PrivateUSB2->DevicePath.AcpiDevicePath.UID = 0;
+ // Copy protocol structure
+ CopyMem(&PrivateUSB2->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
+
+ Status = gBS->InstallMultipleProtocolInterfaces(&HandleUSB2,
+ &gEfiPciIoProtocolGuid, &PrivateUSB2->PciIoProtocol,
+ &gEfiDevicePathProtocolGuid, &PrivateUSB2->DevicePath,
+ NULL);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));
+ }
+
+#if defined(XHCI_SUPPORT)
+ HandleUSB3 = NULL;
+
+ // USB 3.0
+ // Unique device path.
+ CopyMem(&PrivateUSB3->DevicePath, &PciIoDevicePathTemplateUSB3, sizeof(PciIoDevicePathTemplateUSB3));
+ PrivateUSB3->DevicePath.AcpiDevicePath.UID = 1;
+ // Copy protocol structure
+ CopyMem(&PrivateUSB3->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
+
+
+ Status = gBS->InstallMultipleProtocolInterfaces(&HandleUSB3,
+ &gEfiPciIoProtocolGuid, &PrivateUSB3->PciIoProtocol,
+ &gEfiDevicePathProtocolGuid, &PrivateUSB3->DevicePath,
+ NULL);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));
+ }
+#endif
+
+#if defined(OHCI_SUPPORT)
+ HandleUSB1 = NULL;
+
+ // USB 1.0
+ // Unique device path.
+ CopyMem(&PrivateUSB1->DevicePath, &PciIoDevicePathTemplateUSB1, sizeof(PciIoDevicePathTemplateUSB1));
+ PrivateUSB1->DevicePath.AcpiDevicePath.UID = 2;
+ // Copy protocol structure
+ CopyMem(&PrivateUSB1->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
+
+ Status = gBS->InstallMultipleProtocolInterfaces(&HandleUSB1,
+ &gEfiPciIoProtocolGuid, &PrivateUSB1->PciIoProtocol,
+ &gEfiDevicePathProtocolGuid, &PrivateUSB1->DevicePath,
+ NULL);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));
+ }
+#endif
+
+
+ return Status;
+}
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.h
new file mode 100644
index 000000000..7f0e3106e
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.h
@@ -0,0 +1,290 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ 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 _PCI_ROOT_BRIDGE_H_
+#define _PCI_ROOT_BRIDGE_H_
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DmaLib.h>
+
+#include <Protocol/EmbeddedExternalDevice.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+
+#include <IndustryStandard/Pci22.h>
+#include <IndustryStandard/Acpi.h>
+
+
+//#define OHCI_SUPPORT
+#define XHCI_SUPPORT
+
+
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL
+
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+
+#define ACPI_CONFIG_IO 0
+#define ACPI_CONFIG_MMIO 1
+#define ACPI_CONFIG_BUS 2
+
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesc;
+} ACPI_CONFIG_INFO;
+
+
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
+
+ UINT8 StartBus;
+ UINT8 EndBus;
+ UINT16 Type;
+ UINT32 MemoryStart;
+ UINT32 MemorySize;
+ UINTN IoOffset;
+ UINT32 IoStart;
+ UINT32 IoSize;
+ UINT64 PciAttributes;
+
+ ACPI_CONFIG_INFO *Config;
+
+} PCI_ROOT_BRIDGE;
+
+
+#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+
+typedef union {
+ UINT8 volatile *buf;
+ UINT8 volatile *ui8;
+ UINT16 volatile *ui16;
+ UINT32 volatile *ui32;
+ UINT64 volatile *ui64;
+ UINTN volatile ui;
+} PTR;
+
+
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+//
+// Private Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ );
+
+BOOLEAN
+PciIoMemAddressValid (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Address
+ );
+
+EFI_STATUS
+EmulatePciIoForEhci (
+ INTN MvPciIfMaxIf
+ );
+
+#endif
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf
new file mode 100644
index 000000000..f56fe6c04
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf
@@ -0,0 +1,64 @@
+/** @file
+
+ Copyright (c) 2009, Apple Inc. All rights reserved.<BR>
+
+ 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 = ExynosPciEmulation
+ FILE_GUID = feaa2e2b-53ac-4d5e-ae10-1efd5da4a2ba
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PciEmulationEntryPoint
+
+[Sources.common]
+ Exynos5_USB2Phy.h
+ Exynos5_USB3Phy.h
+ Exynos5_USB.c
+ PciRootBridgeIo.c
+ PciEmulation.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+ SamsungPlatformPkg/SamsungPlatformPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DxeServicesTableLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ IoLib
+ DmaLib
+ TimerLib
+
+[Pcd]
+ gExynosPkgTokenSpaceGuid.PcdExynos5250Evt1
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiPciHostBridgeResourceAllocationProtocolGuid
+ gEfiPciIoProtocolGuid
+ gSamsungPlatformGpioProtocolGuid ## GPIO Protocol
+
+[Depex]
+ gEfiMetronomeArchProtocolGuid
+
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciRootBridgeIo.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciRootBridgeIo.c
new file mode 100644
index 000000000..2f5b1aa1d
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciRootBridgeIo.c
@@ -0,0 +1,306 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ 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 "PciEmulation.h"
+
+BOOLEAN
+PciRootBridgeMemAddressValid (
+ IN PCI_ROOT_BRIDGE *Private,
+ IN UINT64 Address
+ )
+{
+ if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+EFI_STATUS
+PciRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ )
+{
+ UINTN Stride;
+ UINTN InStride;
+ UINTN OutStride;
+
+
+ Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ Stride = (UINTN)1 << Width;
+ InStride = InStrideFlag ? Stride : 0;
+ OutStride = OutStrideFlag ? Stride : 0;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ *In.ui8 = *Out.ui8;
+ }
+ break;
+ case EfiPciWidthUint16:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ *In.ui16 = *Out.ui16;
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ *In.ui32 = *Out.ui32;
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE *Private;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (!PciRootBridgeMemAddressValid (Private, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ In.buf = Buffer;
+ Out.buf = (VOID *)(UINTN) Address;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+
+ default:
+ break;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE *Private;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (!PciRootBridgeMemAddressValid (Private, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ In.buf = (VOID *)(UINTN) Address;
+ Out.buf = Buffer;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+
+ default:
+ break;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.c
new file mode 100644
index 000000000..7254bd1fa
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.c
@@ -0,0 +1,120 @@
+/** @file
+ Implement EFI Random Number Generator runtime services via Rng Lib.
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ 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 <Uefi.h>
+
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ArmGicLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/ExynosRng.h>
+
+#include "RngDxe.h"
+
+#define CLKDIV 512
+#define RNGSEL 5
+
+/**
+ * Generates a pseudorandom byte stream of the specified size.
+ *
+ * If Output is NULL, then return FALSE.
+ *
+ * @param[out] Output Pointer to buffer to receive random value
+ * @param[in] Size Size of random bytes to generate
+ *
+ * @retval TRUE Pseudorandom byte stream generated successfully.
+ * @retval FALSE Pseudorandom number generator fails to generate due to lack of entropy.
+ *
+ **/
+EFI_STATUS
+EFIAPI
+RngDxeRandomBytes (
+ IN CONST EFI_RNG_PROTOCOL *This,
+ OUT UINT8 *Output,
+ IN UINTN Size
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 TRNGBase;
+ UINT32 value, count, fifo_addr;
+
+ TRNGBase = PcdGet32(PcdCryptoBase);
+
+ /* Set Clock Divider */
+ MmioWrite32(TRNGBase + TRNG_CLKDIV, CLKDIV);
+
+ /* Select RNG Engine */
+ value = TRNG_ENABLE | TRNG_MANUAL_ENABLE | RNGSEL;
+ MmioWrite32(TRNGBase + TRNG_CTRL, value);
+
+ /* Select and Enable Post Processor */
+ value = TRNG_POST_ENABLE | TRNG_POST_SEL_LFSR;
+ MmioWrite32(TRNGBase + TRNG_POST_CTRL, value);
+
+ /* Disable Online Tester */
+ MmioWrite32(TRNGBase + TRNG_ONLINE_CTRL, 0);
+
+ /* Set FIFO pointer as number of random bits */
+ MmioWrite32(TRNGBase + TRNG_FIFO_CTRL, Size << 3);
+
+ /* Poll FIFO pointer until TRNG_FIFO_CTRL.FIFOPTR == 0 */
+ while (MmioRead32(TRNGBase + TRNG_FIFO_CTRL));
+
+ /* Read TRNG FIFO */
+ for (count = 0; count < (Size >> 2); count++) {
+ fifo_addr = TRNG_FIFO_0 + (count << 2);
+ value = MmioRead32(TRNGBase + fifo_addr);
+ CopyMem((UINT8 *)((UINT32)Output + (count << 2)), &value, sizeof(value));
+ }
+
+ return Status;
+}
+
+EFI_RNG_PROTOCOL gRng = {
+ RngDxeRandomBytes
+};
+
+/**
+ Initialize the state information for the RngDxe
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+RngDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &ImageHandle,
+ &gSamsungPlatformRngProtocolGuid,
+ &gRng,
+ NULL
+ );
+
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.h
new file mode 100644
index 000000000..6a1ab107e
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.h
@@ -0,0 +1,40 @@
+#ifndef __CRYPTRAND_H__
+#define __CRYPTRAND_H__
+
+/*
+ * TRNG SFR Address
+ */
+#define SSS_TRNG_OFFSET (0x600)
+
+#define TRNG_CLKDIV (SSS_TRNG_OFFSET + 0x00)
+#define TRNG_CTRL (SSS_TRNG_OFFSET + 0x20)
+#define TRNG_POST_CTRL (SSS_TRNG_OFFSET + 0x30)
+#define TRNG_ONLINE_CTRL (SSS_TRNG_OFFSET + 0x40)
+#define TRNG_ONLINE_STAT (SSS_TRNG_OFFSET + 0x44)
+#define TRNG_ONLINE_MAXCHI2 (SSS_TRNG_OFFSET + 0x48)
+
+#define TRNG_FIFO_CTRL (SSS_TRNG_OFFSET + 0x50)
+#define TRNG_FIFO_0 (SSS_TRNG_OFFSET + 0x80)
+#define TRNG_FIFO_1 (SSS_TRNG_OFFSET + 0x84)
+#define TRNG_FIFO_2 (SSS_TRNG_OFFSET + 0x88)
+#define TRNG_FIFO_3 (SSS_TRNG_OFFSET + 0x8C)
+#define TRNG_FIFO_4 (SSS_TRNG_OFFSET + 0x90)
+#define TRNG_FIFO_5 (SSS_TRNG_OFFSET + 0x94)
+#define TRNG_FIFO_6 (SSS_TRNG_OFFSET + 0x98)
+#define TRNG_FIFO_7 (SSS_TRNG_OFFSET + 0x9C)
+
+/* TRNG CTRL */
+#define TRNG_ENABLE (0x1 << 31)
+#define TRNG_MANUAL_ENABLE (0x1 << 30)
+
+/* TRNG POST CTRL */
+#define TRNG_POST_ENABLE (0x1 << 31)
+#define TRNG_POST_SEL_BYPASS (0x0 << 0)
+#define TRNG_POST_SEL_LFSR (0x1 << 0)
+#define TRNG_POST_SEL_VON (0x2 << 0)
+#define TRNG_POST_SEL_XOR (0x3 << 0)
+
+/* TRNG ONLINE CTRL */
+#define TRNG_ONLINE_TESTER_ENABLE (0x1 << 31)
+#endif
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.inf
new file mode 100644
index 000000000..87c0e3490
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/RngDxe/RngDxe.inf
@@ -0,0 +1,49 @@
+#/** @file
+# CryptRand library implementation
+#
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = RngDxe
+ FILE_GUID = cc605e80-ef94-4d5c-9153-364c92b0adc1
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RngDxeInitialize
+
+[Sources]
+ RngDxe.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+ SamsungPlatformPkg/SamsungPlatformPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UncachedMemoryAllocationLib
+ DebugLib
+ IoLib
+
+[Guids]
+
+[Protocols]
+ gSamsungPlatformRngProtocolGuid
+
+[Pcd]
+ gExynosPkgTokenSpaceGuid.PcdCryptoBase
+
+[Depex]
+ TRUE
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.c
new file mode 100755
index 000000000..0c3a219a4
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.c
@@ -0,0 +1,1348 @@
+/** @file
+ MMC/SD Card driver for Secure Digital Host Controller
+
+ This driver always produces a BlockIo protocol but it starts off with no Media
+ present. A TimerCallBack detects when media is inserted or removed and after
+ a media change event a call to BlockIo ReadBlocks/WriteBlocks will cause the
+ media to be detected (or removed) and the BlockIo Media structure will get
+ updated. No MMC/SD Card harward registers are updated until the first BlockIo
+ ReadBlocks/WriteBlocks after media has been insterted (booting with a card
+ plugged in counts as an insertion event).
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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/TimerLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/ExynosGpio.h>
+#include <Platform/ArmPlatform.h>
+#include <Platform/Exynos5250.h>
+#include <Platform/Arndale5250.h>
+
+#include "SDHCDxe.h"
+
+
+#define DateInformation "20120810_001"
+
+
+MSHC_OPERATION_MODE MSHC_operation_mode=MSHC_FIFO;
+//MSHC_OPERATION_MODE MSHC_operation_mode=MSHC_IDMA;
+
+
+//#undef EFI_D_INFO
+//#define EFI_D_INFO 1
+
+
+CARD_INFO gCardInfo;
+EFI_EVENT gTimerEvent;
+BOOLEAN gMediaChange = FALSE;
+
+
+EFI_BLOCK_IO_MEDIA gSDMMCMedia = {
+ SIGNATURE_32('s','d','h','c'), // MediaId
+ TRUE, // RemovableMedia
+ FALSE, // MediaPresent
+ FALSE, // LogicalPartition
+ FALSE, // ReadOnly
+ FALSE, // WriteCaching
+ 512, // BlockSize
+ 4, // IoAlign
+ 0, // Pad
+ 0 // LastBlock
+};
+
+typedef struct {
+ VENDOR_DEVICE_PATH Mmc;
+ EFI_DEVICE_PATH End;
+} MSHC_DEVICE_PATH;
+
+MSHC_DEVICE_PATH gMSHCDevicePath = {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
+ 0x3a02e7fe, 0x649, 0x4fb4, 0xbe, 0x4f, 0xa8, 0x62, 0xca, 0x18, 0x72, 0xa9
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0
+ }
+};
+
+
+//
+// Internal Functions
+//
+
+
+VOID
+ParseCardCIDData (
+ UINT32 Response0,
+ UINT32 Response1,
+ UINT32 Response2,
+ UINT32 Response3
+ )
+{
+ gCardInfo.CIDData.MDT = ((Response0 >> 8) & 0xFFF);
+ gCardInfo.CIDData.PSN = (((Response0 >> 24) & 0xFF) | ((Response1 & 0xFFFFFF) << 8));
+ gCardInfo.CIDData.PRV = ((Response1 >> 24) & 0xFF);
+ gCardInfo.CIDData.PNM[4] = ((Response2) & 0xFF);
+ gCardInfo.CIDData.PNM[3] = ((Response2 >> 8) & 0xFF);
+ gCardInfo.CIDData.PNM[2] = ((Response2 >> 16) & 0xFF);
+ gCardInfo.CIDData.PNM[1] = ((Response2 >> 24) & 0xFF);
+ gCardInfo.CIDData.PNM[0] = ((Response3) & 0xFF);
+ gCardInfo.CIDData.OID = ((Response3 >> 8) & 0xFFFF);
+ gCardInfo.CIDData.MID = ((Response3 >> 24) & 0xFF);
+}
+
+
+EFI_STATUS
+MSHC_SendCmd (
+ UINTN Cmd,
+ UINTN CmdInterruptEnableVal,
+ UINTN CmdArgument
+ )
+{
+ UINTN MmcStatus = 0;
+ volatile UINTN RetryCount = 0;
+ int cmd_flags = 0;
+ int timeout=0;
+ UINT32 SdMmcBaseAddr;
+ //UINT32 MSHCRintStatus=0;
+
+ DEBUG ((EFI_D_INFO, "CMD = %d Argument=0x%x\n", (Cmd&0x3F), CmdArgument));
+
+ timeout = MAX_RETRY_COUNT;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ //1. Check if Data busy or not
+ while(MmioRead32(SdMmcBaseAddr + MSHCI_STATUS) & (DATA_BUSY))
+ {
+ if (timeout == 0)
+ {
+ DEBUG ((EFI_D_ERROR, "SDHC::MSHC_SendCmd timeout : CMD = %d\n", Cmd));
+ return EFI_DEVICE_ERROR;
+ }
+ timeout--;
+ MicroSecondDelay(1);
+ }
+
+ // 2. Check if Raw interrupt is command done
+ /*MSHCRintStatus = MmioRead32(SdMmcBaseAddr + MSHCI_RINTSTS);
+ if ((MSHCRintStatus & (INTMSK_CDONE|INTMSK_ACD)) == 0)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd interrupt error : INT = %x\n", MmioRead32(SdMmcBaseAddr + MSHCI_RINTSTS)));
+ } */
+
+ // 3. Clear Raw interrupt
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_RINTSTS), INTMSK_ALL);
+
+ // 4. prepare data
+ //mshci_reset_fifo();
+
+ //5. Set command argument register
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMDARG), CmdArgument);
+
+ // 6. transfer data
+
+ //Enable interrupt enable events to occur
+ // EVT1 do not need interrupt mask, use Raw interrupt
+ //MmioWrite32 ((SdMmcBaseAddr + MSHCI_INTMSK), CmdInterruptEnableVal);
+
+ // 7. trasfer data
+
+ //8. Send a command
+ cmd_flags = (Cmd & 0x3F);
+ if(Cmd & (RSPTYP48 | RSPTYP48B | RSPTYP136))
+ {
+ cmd_flags |= CMD_RESP_EXP_BIT;
+ if(Cmd & RSPTYP136)
+ cmd_flags |= CMD_RESP_LENGTH_BIT;
+ }
+
+ //if((Cmd==CMD17)|(Cmd==CMD18)|(Cmd==CMD8))
+ if((Cmd==CMD17)|(Cmd==CMD18))
+ {
+ cmd_flags |= CMD_DATA_EXP_BIT;
+ //DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Read\n"));
+ }
+
+ if((Cmd==CMD24)|(Cmd==CMD25))
+ {
+ cmd_flags |= CMD_DATA_EXP_BIT | CMD_RW_BIT;
+ //DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Write\n"));
+
+ }
+
+ if (Cmd & ENCMDCRC)
+ {
+ cmd_flags |= CMD_CHECK_CRC_BIT;
+ }
+ //cmd_flags |= (CMD_STRT_BIT | CMD_USE_HOLD_REG | CMD_WAIT_PRV_DAT_BIT|CMD_SENT_AUTO_STOP_BIT);
+ cmd_flags |= (CMD_STRT_BIT | CMD_USE_HOLD_REG | CMD_WAIT_PRV_DAT_BIT);
+ DEBUG ((EFI_D_INFO, "CMD flag = 0x%x\n", cmd_flags));
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), cmd_flags);
+ MicroSecondDelay(1);
+
+ //9. Check for the Raw interrupt
+ //wait for command complete by busy waiting.
+ for (RetryCount; RetryCount<MAX_RETRY_COUNT; RetryCount++)
+ {
+ MmcStatus = MmioRead32(SdMmcBaseAddr + MSHCI_RINTSTS);
+ if (MmcStatus & INTMSK_CDONE)
+ {
+ break;
+ }
+ }
+
+ if (RetryCount == MAX_RETRY_COUNT)
+ {
+ DEBUG ((EFI_D_ERROR, "SDHC::MSHC_SendCmd timeout CMD:%d RINT:0x%x\n",(Cmd&0x3F) ,MmcStatus));
+ return EFI_TIMEOUT;
+ }
+
+ if(MmcStatus & INTMSK_RTO)
+ {
+ DEBUG ((EFI_D_ERROR, "SDHC::MSHC_SendCmd Response timeout CMD:%d RINT:0x%x\n", (Cmd & 0x3F),MmcStatus));
+ return EFI_TIMEOUT;
+
+ }
+ else if (MmcStatus & INTMSK_RE)
+ {
+ DEBUG ((EFI_D_ERROR, "SDHC::MSHC_SendCmd Response Error RINT:0x%x\n", MmcStatus));
+ return EFI_TIMEOUT;
+ }
+ else if(MmcStatus & INTMSK_RCRC)
+ DEBUG ((EFI_D_ERROR, "SDHC::MSHC_SendCmd Response CRC Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_DCRC)
+ DEBUG ((EFI_D_ERROR, "SDHC::MSHC_SendCmd Data CRC Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_HLE)
+ DEBUG ((EFI_D_ERROR, "SDHC::MSHC_SendCmd HLE Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_SBE)
+ DEBUG ((EFI_D_ERROR, "SDHC::MSHC_SendCmd SBE Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_EBE)
+ DEBUG ((EFI_D_ERROR, "SDHC::MSHC_SendCmd EBE Err RINT:0x%x\n", MmcStatus));
+
+ return EFI_SUCCESS;
+}
+
+static const UINT32 FreqUnit[4]={10, 100, 1000, 10000};
+static const UINT8 MultiFactor[16]={0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80};
+
+void PrintCardInfo()
+{
+#if !defined(MDEPKG_NDEBUG)
+ UINT8 TransSpeed = gCardInfo.CSDData.TRAN_SPEED;
+
+ DEBUG ((EFI_D_INFO, "SDHC::READ_BL_LEN %d\n", gCardInfo.CSDData.READ_BL_LEN));
+ DEBUG ((EFI_D_INFO, "SDHC::CSize %d\n", gCardInfo.CSDData.C_SIZELow2 | (gCardInfo.CSDData.C_SIZEHigh10 << 2)));
+ DEBUG ((EFI_D_INFO, "SDHC::MULTI %d\n", gCardInfo.CSDData.C_SIZE_MULT));
+ DEBUG ((EFI_D_INFO, "SDHC::Speed %d\n", (FreqUnit[TransSpeed&0x7]*MultiFactor[TransSpeed>>3])));
+#endif
+}
+
+
+#define EXT_CSD_SIZE 128
+UINT32 Ext_csd[EXT_CSD_SIZE];
+VOID GetEXTCSD()
+{
+ gCardInfo.NumBlocks = 0x1D4C000;
+ DEBUG ((EFI_D_INFO, "SDHC:: default block number : 0x1D4C000"));
+
+ UINTN cmdarg = 0;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_HS_TIMING << 16) |
+ (0 << 8);
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, cmdarg);
+
+ cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_BUS_WIDTH << 16) |
+ (EXT_CSD_BUS_WIDTH_1 << 8);
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, cmdarg);
+
+ cmdarg = 0;
+ Status = MSHC_SendCmd (CMD8, CMD8_INT_EN, cmdarg);
+
+ gCardInfo.BlockSize = BLEN_512BYTES;
+
+ if (!EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_INFO, "SDHC::EXT CSD \n"));
+ PrepareTransfer(&Ext_csd[0], 1, READ);
+ //MSHC_ReadDMA(&Ext_csd[0], 1);
+ MSHC_ReadFIFO(EXT_CSD_SIZE, &Ext_csd[0]);
+ gCardInfo.NumBlocks = Ext_csd[EXT_CSD_SEC_CNT/4];
+ MicroSecondDelay(1000);
+ DEBUG ((1, "SDHC::Size:%dMB\n", (gCardInfo.NumBlocks/2048)));
+ }
+
+}
+
+VOID
+GetBlockInformation (
+ UINTN *BlockSize,
+ UINTN *NumBlocks
+ )
+{
+ CSD_SDV2 *CsdSDV2Data;
+ UINTN CardSize;
+
+
+ if (gCardInfo.CardType == SD_CARD_2_HIGH) {
+ CsdSDV2Data = (CSD_SDV2 *)&gCardInfo.CSDData;
+
+ //Populate BlockSize.
+ *BlockSize = (0x1UL << CsdSDV2Data->READ_BL_LEN);
+
+ //Calculate Total number of blocks.
+ CardSize = CsdSDV2Data->C_SIZELow16 | (CsdSDV2Data->C_SIZEHigh6 << 2);
+ *NumBlocks = ((CardSize + 1) * 1024);
+ }
+ else if(gCardInfo.CardType == MMC_CARD)
+ {
+ //Populate BlockSize.
+ *BlockSize = (0x1UL << gCardInfo.CSDData.READ_BL_LEN);
+
+ //Calculate Total number of blocks.
+ CardSize = gCardInfo.CSDData.C_SIZELow2 | (gCardInfo.CSDData.C_SIZEHigh10 << 2);
+ *NumBlocks = (CardSize + 1) * (1 << (gCardInfo.CSDData.C_SIZE_MULT + 2));
+ *NumBlocks *= (*BlockSize);
+ }
+
+ //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
+ if (*BlockSize > 512) {
+ DEBUG ((EFI_D_INFO, "SDHC::BlockSize:%d\n", *BlockSize));
+ *NumBlocks = MultU64x32(*NumBlocks, *BlockSize/2);
+ *BlockSize = 512;
+ }
+
+ DEBUG ((EFI_D_INFO, "Card type: 0x%x, BlockSize: 0x%x, NumBlocks: 0x%x\n", gCardInfo.CardType, *BlockSize, *NumBlocks));
+}
+
+
+VOID
+GetCardConfigurationData (
+ VOID
+ )
+{
+ UINTN BlockSize;
+ UINTN NumBlocks;
+ // UINTN ClockFrequencySelect;
+
+ //Calculate BlockSize and Total number of blocks in the detected card.
+ GetBlockInformation(&BlockSize, &NumBlocks);
+ gCardInfo.BlockSize = BlockSize;
+ gCardInfo.NumBlocks = NumBlocks;
+
+}
+
+EFI_STATUS
+PerformCardIdenfication (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN CmdArgument = 0;
+ UINTN Response = 0;
+ UINTN RetryCount = 0;
+ UINTN TempRes0,TempRes1,TempRes2,TempRes3;
+ BOOLEAN SDCmd8Supported = FALSE;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ //Send CMD0 command.
+ Status = MSHC_SendCmd (CMD0, CMD0_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "Cmd0 fails.\n"));
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD0 response: %x\n", MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0))));
+
+ //Send CMD8 command. (New v2.00 command for Voltage check)
+ //Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass.
+ //MMC & SD1.1 card will fail this command.
+ CmdArgument = CMD8_ARG;
+ Status = MSHC_SendCmd (CMD8, CMD8_INT_EN, CmdArgument);
+ if (Status == EFI_SUCCESS) {
+ Response = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+ DEBUG ((EFI_D_INFO, "CMD8 success. CMD8 response: %x\n", Response));
+ if (Response != CmdArgument) {
+ return EFI_DEVICE_ERROR;
+ }
+ DEBUG ((EFI_D_INFO, "Card is SD2.0\n"));
+ SDCmd8Supported = TRUE; //Supports high capacity.
+ } else {
+ DEBUG ((EFI_D_INFO, "CMD8 fails. Not an SD2.0 card.\n"));
+ }
+
+ //Poll till card is busy
+ while (RetryCount < MAX_RETRY_COUNT) {
+ //Send CMD55 command.
+ CmdArgument = 0;
+ Status = MSHC_SendCmd (CMD55, CMD55_INT_EN, CmdArgument);
+ if (Status == EFI_SUCCESS) {
+ DEBUG ((EFI_D_INFO, "CMD55 success. CMD55 response: %x\n", MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0))));
+ gCardInfo.CardType = SD_CARD;
+ } else {
+ DEBUG ((EFI_D_ERROR, "CMD55 fails.\n"));
+ gCardInfo.CardType = MMC_CARD;
+ }
+
+ //Send appropriate command for the card type which got detected.
+ if (gCardInfo.CardType == SD_CARD) {
+ CmdArgument = ((UINTN *) &(gCardInfo.OCRData))[0];
+
+ //Set HCS bit.
+ if (SDCmd8Supported) {
+ CmdArgument |= HCS;
+ }
+
+ Status = MSHC_SendCmd (ACMD41, ACMD41_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "ACMD41 fails.\n"));
+ return Status;
+ }
+ ((UINT32 *) &(gCardInfo.OCRData))[0] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+ DEBUG ((EFI_D_INFO, "SD card detected. ACMD41 OCR: %x\n", ((UINT32 *) &(gCardInfo.OCRData))[0]));
+ } else if (gCardInfo.CardType == MMC_CARD) {
+ CmdArgument = 0;
+ Status = MSHC_SendCmd (CMD1, CMD1_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD1 fails.\n"));
+ return Status;
+ }
+ Response = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+ DEBUG ((EFI_D_INFO, "MMC card detected. CMD1 response: %x\n", Response));
+
+ //NOTE: For now, I am skipping this since I only have an SD card.
+ //Compare card OCR and host OCR (Section 22.6.1.3.2.4)
+ return EFI_UNSUPPORTED; //For now, MMC is not supported.
+ }
+
+ //Poll the card until it is out of its power-up sequence.
+ if (gCardInfo.OCRData.Busy == 1) {
+
+ if (SDCmd8Supported) {
+ gCardInfo.CardType = SD_CARD_2;
+ }
+
+ //Card is ready. Check CCS (Card capacity status) bit (bit#30).
+ //SD 2.0 standard card will response with CCS 0, SD high capacity card will respond with CCS 1.
+ if (gCardInfo.OCRData.AccessMode & BIT1) {
+ gCardInfo.CardType = SD_CARD_2_HIGH;
+ DEBUG ((EFI_D_INFO, "High capacity card.\n"));
+ } else {
+ DEBUG ((EFI_D_INFO, "Standard capacity card.\n"));
+ }
+
+ break;
+ }
+
+ gBS->Stall(1000);
+ RetryCount++;
+ }
+
+ if (RetryCount == MAX_RETRY_COUNT) {
+ DEBUG ((EFI_D_ERROR, "Timeout error. RetryCount: %d\n", RetryCount));
+ return EFI_TIMEOUT;
+ }
+
+ //Read CID data.
+ CmdArgument = 0;
+ Status = MSHC_SendCmd (CMD2, CMD2_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD2 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD2 response: %x %x %x %x\n", MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0)), \
+ MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP1)), \
+ MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP2)), \
+ MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP3))));
+
+ TempRes0 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+ TempRes1 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP1));
+ TempRes2 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP2));
+ TempRes3 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP3));
+
+ //Parse CID register data.
+ ParseCardCIDData(TempRes0 << 8, (TempRes1 << 8) | (TempRes0 >> 24),
+ (TempRes2 << 8) | (TempRes1 >> 24), (TempRes3 << 8) | (TempRes2 >> 24));
+
+ //Read RCA
+ CmdArgument = 0;
+ Status = MSHC_SendCmd (CMD3, CMD3_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD3 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ //Set RCA for the detected card. RCA is CMD3 response.
+ gCardInfo.RCA = (MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0)) >> 16);
+ DEBUG ((EFI_D_INFO, "CMD3 response: RCA %x\n", gCardInfo.RCA));
+
+ gBS->Stall(1000); //Need Debug by wprkfgur
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+GetCardSpecificData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN CmdArgument;
+ UINTN TempRes[4],i;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ //Send CMD9 to retrieve CSD.
+ CmdArgument = gCardInfo.RCA << 16;
+ Status = MSHC_SendCmd (CMD9, CMD9_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD9 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ TempRes[0] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+ TempRes[1] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP1));
+ TempRes[2] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP2));
+ TempRes[3] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP3));
+
+ //Populate 128-bit CSD register data.
+
+ for (i = 0 ; i < 4; i++) {
+ ((UINT32 *)&(gCardInfo.CSDData))[i] = TempRes[i];
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD9 response: %x %x %x %x\n", ((UINT32 *)&(gCardInfo.CSDData))[0], ((UINT32 *)&(gCardInfo.CSDData))[1], ((UINT32 *)&(gCardInfo.CSDData))[2], ((UINT32 *)&(gCardInfo.CSDData))[3]));
+ PrintCardInfo();
+ //Calculate total number of blocks and max. data transfer rate supported by the detected card.
+ GetCardConfigurationData();
+ return Status;
+}
+
+EFI_STATUS
+PerformCardConfiguration (
+ VOID
+ )
+{
+ UINTN CmdArgument = 0;
+ EFI_STATUS Status;
+ UINT32 SdMmcBaseAddr;
+ //UINTN FifoCount = 0;
+ //UINTN Count=0;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ //Send CMD7
+ CmdArgument = gCardInfo.RCA << 16;
+ Status = MSHC_SendCmd (CMD7, CMD7_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD7 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ if ((gCardInfo.CardType != UNKNOWN_CARD) && (gCardInfo.CardType != MMC_CARD)) {
+ // We could read SCR register, but SD Card Phys spec stats any SD Card shall
+ // set SCR.SD_BUS_WIDTHS to support 4-bit mode, so why bother?
+
+ // Send ACMD6 (application specific commands must be prefixed with CMD55)
+ Status = MSHC_SendCmd (CMD55, CMD55_INT_EN, CmdArgument);
+ if (!EFI_ERROR (Status)) {
+ // set device into 4-bit data bus mode
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, 0x2);
+ if (!EFI_ERROR (Status)) {
+ // Set host controler into 4-bit mode
+ MmioOr32 ((SdMmcBaseAddr + MSHCI_CTYPE), CARD_WIDTH14);
+ DEBUG ((EFI_D_INFO, "SD Memory Card set to 4-bit mode\n"));
+ }
+ }
+ }
+
+ //Send CMD16 to set the block length
+ CmdArgument = gCardInfo.BlockSize;
+ Status = MSHC_SendCmd (CMD16, CMD16_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD16 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReadBlockData (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ OUT VOID *Buffer,
+ IN UINTN BlockCount
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ UINTN DataSize = This->Media->BlockSize/4;
+
+ DEBUG ((EFI_D_INFO, "SDHC::ReadBlockData start \n"));
+
+ if(MSHC_operation_mode == MSHC_FIFO)
+ {
+ Status = MSHC_ReadFIFO(DataSize, Buffer);
+ }
+
+ else if(MSHC_operation_mode == MSHC_IDMA)
+ {
+ Status = MSHC_ReadDMA(Buffer, BlockCount);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+WriteBlockData (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ OUT VOID *Buffer,
+ IN UINTN BlockCount
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ UINTN DataSize = This->Media->BlockSize/4;
+
+ if(MSHC_operation_mode == MSHC_FIFO)
+ {
+ Status = MSHC_WriteFIFO(DataSize, Buffer);
+ }
+ else if(MSHC_operation_mode == MSHC_IDMA)
+ {
+ Status = MSHC_WriteDMA(Buffer, BlockCount);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+TransferBlock (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Lba,
+ IN OUT VOID *Buffer,
+ IN UINTN BlockCount,
+ IN OPERATION_TYPE OperationType
+ )
+{
+ EFI_STATUS Status;
+ UINTN Cmd = 0;
+ UINTN CmdInterruptEnable = 0;
+ UINTN CmdArgument = 0;
+
+ // 1. FIFO reset
+ // MSHC_SendCmd do the fifo reset
+
+ // 2. prepare transfer
+
+ DEBUG ((EFI_D_INFO, "SDHC::TransferBlock : Lba = %d, Buffer = 0x%x, Type = %d\n", Lba, Buffer, OperationType));
+ //Populate the command information based on the operation type.
+ if (OperationType == READ)
+ {
+ if(BlockCount>1)
+ {
+ Cmd = CMD18; //multi block read
+ CmdInterruptEnable = CMD18_INT_EN;
+ }
+ else
+ {
+ Cmd = CMD17; //Single block read
+ CmdInterruptEnable = CMD17_INT_EN;
+ }
+
+ }
+ else if (OperationType == WRITE)
+ {
+ if(BlockCount>1)
+ {
+ Cmd = CMD25; //multi block write
+ CmdInterruptEnable = CMD25_INT_EN;
+ }
+ else
+ {
+ Cmd = CMD24; //Single block write
+ CmdInterruptEnable = CMD24_INT_EN;
+ }
+ }
+ PrepareTransfer(Buffer, BlockCount, OperationType);
+
+ //Set command argument based on the card access mode (Byte mode or Block mode)
+ if (gCardInfo.OCRData.AccessMode & BIT1) {
+ CmdArgument = Lba;
+ } else {
+ CmdArgument = Lba * This->Media->BlockSize;
+ }
+
+ //Send Command.
+ Status = MSHC_SendCmd (Cmd, CmdInterruptEnable, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD%d fails. Status: %x\n", (Cmd&0x3F), Status));
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD%d succeed! \n", (Cmd&0x3F)));
+
+ //Read or Write data.
+ if (OperationType == READ) {
+ Status = ReadBlockData (This, Buffer, BlockCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "ReadBlockData fails.\n"));
+ return Status;
+ }
+ } else if (OperationType == WRITE) {
+ Status = WriteBlockData (This, Buffer, BlockCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "WriteBlockData fails.\n"));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+CardPresent (
+ VOID
+ )
+{
+ EXYNOS_GPIO *Gpio;
+ EFI_STATUS Status;
+ UINT32 Val;
+
+ Status = gBS->LocateProtocol(&gSamsungPlatformGpioProtocolGuid, NULL, (VOID **)&Gpio);
+ ASSERT_EFI_ERROR(Status);
+
+ Gpio->Get(Gpio,SD_2_EVT1_CDn,&Val);
+
+ if(Val)
+ {
+ //DEBUG((EFI_D_INFO, "SDHC::CardPresent %d\n", Val));
+ return FALSE;
+ }
+ else
+ return TRUE;
+
+}
+
+EFI_STATUS
+DetectCard (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ //UINT32 SdMmcBaseAddr;
+
+ //DEBUG ((EFI_D_INFO, "===================================\n"));
+ DEBUG ((EFI_D_INFO, "===SDHC: Version %a ===\n", DateInformation));
+ //DEBUG ((EFI_D_INFO, "===================================\n"));
+
+ //SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ if (!CardPresent ()) {
+ return EFI_NO_MEDIA;
+ }
+
+ //Initialize MMC host controller clocks.
+ Status = InitializeMSHC ();
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "Initialize MMC host controller fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ // EVT1 InitializeSDHC do the SW Reset
+ //Soft reset for all.
+ //MmioWrite32((SdMmcBaseAddr + SDHC_SWRST_OFFSET), SRA);
+ //gBS->Stall(1000);
+ //while ((MmioRead32 ((SdMmcBaseAddr + SDHC_SWRST_OFFSET)) & SRA) != 0x0);
+
+ //Set the clock frequency to 400KHz.
+ UpdateMSHCClkFrequency (MSHC_CLK_400);
+
+ //Card idenfication
+ Status = PerformCardIdenfication ();
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "No MMC/SD card detected.\n"));
+ return Status;
+ }
+
+ //Get CSD (Card specific data) for the detected card.
+ Status = GetCardSpecificData();
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //Configure the card in data transfer mode.
+ Status = PerformCardConfiguration();
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+
+ //Patch the Media structure.
+ gSDMMCMedia.LastBlock = (gCardInfo.NumBlocks - 1);
+ gSDMMCMedia.BlockSize = gCardInfo.BlockSize;
+ // gSDMMCMedia.BlockSize = 512;
+ gSDMMCMedia.ReadOnly = 0;
+ gSDMMCMedia.MediaPresent = TRUE;
+ gSDMMCMedia.MediaId++;
+
+ UpdateMSHCClkFrequency(MSHC_CLK_25M);
+ DEBUG ((EFI_D_INFO, "SD Card Media Change on Handle 0x%08x\n", gImageHandle));
+
+ return Status;
+}
+
+
+EFI_STATUS
+SdReadWrite (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Lba,
+ OUT VOID *Buffer,
+ IN UINTN BufferSize,
+ IN OPERATION_TYPE OperationType
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN RetryCount = 0;
+ UINTN BlockCount;
+ UINTN BytesToBeTranferedThisPass = 0;
+ UINTN BytesRemainingToBeTransfered=0;
+ EFI_TPL OldTpl;
+ BOOLEAN Update;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+ Update = FALSE;
+
+ DEBUG ((EFI_D_INFO, "SDHC::SDHCInitialize is called \n"));
+ if (gMediaChange) {
+ Update = TRUE;
+ Status = DetectCard();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "SDHC::SDHCInitialize:Card Detect Fail\n"));
+ gSDMMCMedia.MediaPresent = FALSE;
+ gSDMMCMedia.LastBlock = 0;
+ gSDMMCMedia.BlockSize = 512; // Should be zero but there is a bug in DiskIo
+ gSDMMCMedia.ReadOnly = FALSE;
+ }
+ gMediaChange = FALSE;
+ } else if (!gSDMMCMedia.MediaPresent) {
+ Status = EFI_NO_MEDIA;
+ goto Done;
+ }
+
+ if (Update) {
+ DEBUG ((EFI_D_INFO, "SD Card ReinstallProtocolInterface ()\n"));
+ gBS->ReinstallProtocolInterface (
+ gImageHandle,
+ &gEfiBlockIoProtocolGuid,
+ &gBlockIo,
+ &gBlockIo);
+ }
+DEBUG ((EFI_D_INFO, "SDHC::SDHCInitialize:CardInfo : LastBlock = %ld, BlockSize = %d\n", gSDMMCMedia.LastBlock, gSDMMCMedia.BlockSize));
+
+
+ if (Buffer == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (Lba > This->Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((BufferSize % This->Media->BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Done;
+ }
+
+ //Check if the data lines are not in use.
+ while ((RetryCount++ < MAX_RETRY_COUNT) && (MmioRead32 ((SdMmcBaseAddr + MSHCI_STATUS)) & DATA_BUSY));
+ if (RetryCount == MAX_RETRY_COUNT) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((EFI_D_ERROR, "MSHC::SdReadWrite EFI_TIMEOUT\n"));
+ goto Done;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ BytesRemainingToBeTransfered = BufferSize;
+
+ if(MSHC_operation_mode == MSHC_IDMA)
+ {
+ while (BytesRemainingToBeTransfered > 0) {
+ // Turn OFF DMA path until it is debugged
+ BytesToBeTranferedThisPass = (BytesRemainingToBeTransfered >= MAX_MSHC_TRANSFER_SIZE) ? MAX_MSHC_TRANSFER_SIZE : BytesRemainingToBeTransfered;
+ //BytesToBeTranferedThisPass = This->Media->BlockSize;
+
+ BlockCount = BytesToBeTranferedThisPass/This->Media->BlockSize;
+ Status = TransferBlock (This, Lba, Buffer,BlockCount, OperationType);
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));
+ goto DoneRestoreTPL;
+ }
+
+ BytesRemainingToBeTransfered -= BytesToBeTranferedThisPass;
+ Lba += BlockCount;
+ Buffer = (UINT8 *)Buffer + (This->Media->BlockSize*BlockCount);
+ DEBUG ((EFI_D_INFO, "SdReadWrite::Buf:0x%x, ToBe:0x%x Rema:0x%x \n", BufferSize, BytesToBeTranferedThisPass, BytesRemainingToBeTransfered));
+ }
+ }
+ else
+ {
+ while (BytesRemainingToBeTransfered > 0) {
+ // Turn OFF DMA path until it is debugged
+ // BytesToBeTranferedThisPass = (BytesToBeTranferedThisPass >= MAX_SDHC_TRANSFER_SIZE) ? MAX_SDHC_TRANSFER_SIZE : BytesRemainingToBeTransfered;
+ BytesToBeTranferedThisPass = This->Media->BlockSize;
+
+ BlockCount = BytesToBeTranferedThisPass/This->Media->BlockSize;
+
+ if (BlockCount > 1) {
+ // Status = DmaBlocks (This, Lba, Buffer, BlockCount, OperationType);
+ } else {
+ //Transfer a block worth of data.
+ Status = TransferBlock (This, Lba, Buffer, BlockCount,OperationType);
+
+ }
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));
+ goto DoneRestoreTPL;
+ }
+
+ BytesRemainingToBeTransfered -= BytesToBeTranferedThisPass;
+ Lba += BlockCount;
+ Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
+ }
+
+ }
+
+
+DoneRestoreTPL:
+
+ gBS->RestoreTPL (OldTpl);
+
+Done:
+ return Status;
+
+}
+
+
+/**
+
+ Reset the Block Device.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+
+
+ @retval EFI_SUCCESS The device was reset.
+
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+
+ not be reset.
+
+
+
+**/
+EFI_STATUS
+EFIAPI
+MSHCReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ DEBUG ((EFI_D_INFO, " MSHC::MSHCReset is called\n"));
+ MSHC_reset_all();
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Read BufferSize bytes from Lba into Buffer.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+ @param MediaId Id of the media, changes every time the media is replaced.
+
+ @param Lba The starting Logical Block Address to read from
+
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+
+ responsible for either having implicit or explicit ownership of the buffer.
+
+
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+
+ or the buffer is not on proper alignment.
+
+EFI_STATUS
+
+**/
+
+
+#define EMMC_TEST 0
+#if EMMC_TEST
+#define EMMC_TEST_SIZE (512*2)//(MAX_MSHC_TRANSFER_SIZE+1024)
+UINT32 bWrite[EMMC_TEST_SIZE];
+UINT32 bRead[EMMC_TEST_SIZE];
+//INTN EFIAPI CompareMem (IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
+//two buffers are identical, then 0 is returned. Otherwise, the value returned is the first mismatched byte
+
+void MSHC_Test( IN EFI_BLOCK_IO_PROTOCOL *This)
+{
+ UINTN i=0;
+ UINTN Count;
+ INTN ret;
+ EFI_STATUS Status;
+ DEBUG ((EFI_D_INFO, "MSHC::Read Write test %dB\n", EMMC_TEST_SIZE));
+
+ for(i=0; i<EMMC_TEST_SIZE; i++)
+ {
+ bWrite[i]=i;
+ }
+
+//multi
+ for(Count=100000; Count<100002; Count++)
+ {
+ //Lba=n;
+ //DEBUG ((EFI_D_INFO, "MSHC::Read Write test : %d\n", Count));
+ ZeroMem (&bRead[0], sizeof(bRead));
+ DEBUG ((EFI_D_INFO, "ZR : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bRead[0], bRead[1], bRead[2], bRead[3]));
+
+ Status = SdReadWrite (This, (UINTN)Count, &bWrite[0], EMMC_TEST_SIZE, WRITE);
+ Status = SdReadWrite (This, (UINTN)Count, &bRead[0], EMMC_TEST_SIZE, READ);
+
+ DEBUG ((EFI_D_INFO, "W: 0x%x, 0x%x, 0x%x, 0x%x ",
+ bWrite[0], bWrite[1], bWrite[2], bWrite[3]));
+ DEBUG ((EFI_D_INFO, "R : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bRead[0], bRead[1], bRead[2], bRead[3]));
+
+ ret = CompareMem(&bRead[0],&bWrite[0],EMMC_TEST_SIZE);
+
+ if(ret==0)
+ DEBUG ((1, "SDHC::Read Write OK!!\n\n"));
+ else
+ DEBUG ((1, "SDHC::Read Write Failed bWrite[%d]=0x%x : bRead[%d]=0x%x\n", ret, bWrite[ret], ret, bRead[ret]));
+
+
+ }
+
+
+}
+#endif
+
+EFI_STATUS
+EFIAPI
+MSHCReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ DEBUG ((EFI_D_INFO, "SDHC::MSHCReadBlocks : MediaId = %x, Lba = %d, BufferSize = %d, Buffer = 0x%x\n",
+ MediaId, (UINTN)Lba, BufferSize, Buffer));
+
+#if EMMC_TEST
+ MSHC_Test(This);
+#else
+ //Perform Read operation.
+ Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, READ);
+#endif
+ return Status;
+
+}
+
+
+/**
+
+ Write BufferSize bytes from Lba into Buffer.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+ @param MediaId The media ID that the write request is for.
+
+ @param Lba The starting logical block address to be written. The caller is
+
+ responsible for writing to only legitimate locations.
+
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+
+ @param Buffer A pointer to the source buffer for the data.
+
+
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+
+ or the buffer is not on proper alignment.
+
+
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+MSHCWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+#if EMMC_TEST
+ UINT32 Count=0;
+ UINT32 ret;
+#endif
+
+ DEBUG ((EFI_D_INFO, "SDHC::MSHCWriteBlocks : MediaId = 0x%x, Lba = %d, BufferSize = %d, Buffer = 0x%x\n",
+ MediaId, (UINTN)Lba, BufferSize, Buffer));
+
+ //Perform write operation.
+ Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, WRITE);
+
+#if EMMC_TEST
+ Count = (BufferSize >= MAX_MSHC_TRANSFER_SIZE) ? MAX_MSHC_TRANSFER_SIZE : BufferSize;
+ DEBUG ((1, "\nMSHC::Read Write Test [0x%x] Start \n", Count));
+ ZeroMem (&bRead[0], sizeof(bRead));
+ CopyMem(&bWrite[0], (VOID *)Buffer, Count);
+ Status = SdReadWrite (This, (UINTN)Lba, &bRead[0], Count, READ);
+ DEBUG ((1, "W : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bWrite[7], bWrite[8], bWrite[9], bWrite[10]));
+
+ DEBUG ((1, "R : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bRead[7], bRead[8], bRead[9], bRead[10]));
+
+ ret = CompareMem(&bRead[0],&bWrite[0],Count);
+
+ if(ret==0)
+ DEBUG ((1, "SDHC::Read Write Test OK!!\n"));
+ else
+ DEBUG ((1, "SDHC::Read Write Test Failed -.- bRead[%d]=0x%x bWrite[%d]=0x%x \n", ret, bRead[ret], ret, bWrite[ret]));
+
+#endif
+
+ return Status;
+
+}
+
+
+/**
+
+ Flush the Block Device.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+
+
+ @retval EFI_SUCCESS All outstanding data was written to the device
+
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
+
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+
+
+**/
+EFI_STATUS
+EFIAPI
+MSHCFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ DEBUG ((EFI_D_INFO, "SDHC::MSHCFlushBlocks is called\n"));
+ return EFI_SUCCESS;
+}
+
+
+EFI_BLOCK_IO_PROTOCOL gBlockIo = {
+ EFI_BLOCK_IO_INTERFACE_REVISION, // Revision
+ &gSDMMCMedia, // *Media
+ MSHCReset, // Reset
+ MSHCReadBlocks, // ReadBlocks
+ MSHCWriteBlocks, // WriteBlocks
+ MSHCFlushBlocks // FlushBlocks
+};
+
+/**
+
+ Timer callback to convert card present hardware into a boolean that indicates
+
+ a media change event has happened. If you just check the GPIO you could see
+
+ card 1 and then check again after card 1 was removed and card 2 was inserted
+
+ and you would still see media present. Thus you need the timer tick to catch
+
+ the toggle event.
+
+
+
+ @param Event Event whose notification function is being invoked.
+
+ @param Context The pointer to the notification function's context,
+
+ which is implementation-dependent. Not used.
+
+
+
+**/
+VOID
+EFIAPI
+TimerCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ BOOLEAN Present;
+
+ //DEBUG ((EFI_D_ERROR, "SDHC::TimerCallBack is called\n"));
+ Present = CardPresent ();
+ if (gSDMMCMedia.MediaPresent) {
+ if (!Present && !gMediaChange) {
+ gMediaChange = TRUE;
+ }
+ } else {
+ if (Present && !gMediaChange) {
+ gMediaChange = TRUE;
+ }
+ }
+}
+
+EFI_HANDLE mHandle = NULL;
+EFI_EVENT mCommandProtocolRegistration=NULL;
+
+VOID
+EFIAPI
+CommandProtocolNotificationEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ if(mHandle!=NULL){
+ return;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiBlockIoProtocolGuid, &gBlockIo,
+ &gEfiDevicePathProtocolGuid, &gMSHCDevicePath,
+ NULL
+ );
+ DEBUG((EFI_D_INFO, "SDHC::install protocol \n" ));
+ if(Status!=EFI_SUCCESS)
+ {
+ DEBUG((EFI_D_ERROR, "SDHC::install protocol fail %r\n", Status));
+ }
+}
+
+
+
+EFI_STATUS
+EFIAPI
+SDHCInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&gCardInfo, sizeof (CARD_INFO));
+
+ Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, TimerCallback, NULL, &gTimerEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->SetTimer (gTimerEvent, TimerPeriodic, 1000000);
+ ASSERT_EFI_ERROR (Status);
+
+ EfiCreateProtocolNotifyEvent (
+ &gEfiEblAddCommandProtocolGuid,
+ TPL_CALLBACK,
+ CommandProtocolNotificationEvent,
+ (VOID *)SystemTable,
+ &mCommandProtocolRegistration
+ );
+
+#if 0
+ //Publish BlockIO.
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiBlockIoProtocolGuid, &gBlockIo,
+ &gEfiDevicePathProtocolGuid, &gMSHCDevicePath,
+ NULL
+ );
+#endif
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.h
new file mode 100755
index 000000000..29f317b19
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.h
@@ -0,0 +1,259 @@
+/** @file
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 _MSHCDXE_H_
+#define _MSHCDXE_H_
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/EblAddCommand.h>
+#include <Library/UefiLib.h>
+
+#include "SDHCDxe_5250.h"
+#include "SDHCDxe_CMD.h"
+
+
+#define MSHC_BOOT_SIZE 100 //100M
+#define MSHC_RPMB_SIZE 0
+
+#define MSHC_EMMC_OCR 0xC0FF8080
+
+#define BLEN_512BYTES (0x200)
+#define BLKSIZE_1 (0x1)
+
+
+#define MAX_RETRY_COUNT (100000)
+#define MMC_REFERENCE_CLK (96000000)
+#define MSHC_CLK_400 (400)
+#define MSHC_CLK_25M (25000)
+#define MSHC_CLK_50M (50000)
+
+#define OCR_BUSY 0x80000000
+#define OCR_HCS 0x40000000
+
+#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
+#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
+
+
+#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in EXT_CSD byte
+ addressed by index which are
+ 1 in value field */
+#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits in EXT_CSD byte
+ addressed by index, which are
+ 1 in value field */
+#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target byte to value */
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BUS_WIDTH 183 /* R/W */
+#define EXT_CSD_HS_TIMING 185 /* R/W */
+#define EXT_CSD_CARD_TYPE 196 /* RO */
+#define EXT_CSD_REV 192 /* RO */
+#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
+#define BOOT_SIZE_MULTI 226 /* RO */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+/* Card */
+#define EXT_CSD_CMD_SET_NORMAL (1<<0)
+#define EXT_CSD_CMD_SET_SECURE (1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
+
+#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_52_DDR_18_30 (1<<2) /* Card can run at 52MHz DDR 1.8V or 3V */
+#define EXT_CSD_CARD_TYPE_52_DDR_12 (1<<3) /* Card can run at 52MHz DDR 1.2V */
+
+#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
+#define EXT_CSD_BUS_WIDTH_4_DDR 5 /* Card is in 4 bit DDR mode */
+#define EXT_CSD_BUS_WIDTH_8_DDR 6 /* Card is in 8 bit DDR mode */
+
+
+typedef struct {
+ UINT32 hs_max_dtr;
+ UINT32 sectors;
+ UINT32 boot_size_multi;
+}mmc_ext_csd;
+
+
+typedef struct {
+ UINT32 Reserved0: 7; // 0
+ UINT32 V170_V195: 1; // 1.70V - 1.95V
+ UINT32 V200_V260: 7; // 2.00V - 2.60V
+ UINT32 V270_V360: 9; // 2.70V - 3.60V
+ UINT32 RESERVED_1: 5; // Reserved
+ UINT32 AccessMode: 2; // 00b (byte mode), 10b (sector mode)
+ UINT32 Busy: 1; // This bit is set to LOW if the card has not finished the power up routine
+}OCR;
+
+typedef struct {
+ UINT32 NOT_USED; // 1 [0:0]
+ UINT32 CRC; // CRC7 checksum [7:1]
+ UINT32 MDT; // Manufacturing date [19:8]
+ UINT32 RESERVED_1; // Reserved [23:20]
+ UINT32 PSN; // Product serial number [55:24]
+ UINT8 PRV; // Product revision [63:56]
+ UINT8 PNM[5]; // Product name [64:103]
+ UINT16 OID; // OEM/Application ID [119:104]
+ UINT8 MID; // Manufacturer ID [127:120]
+}CID;
+
+typedef struct {
+ UINT8 NOT_USED: 1; // Not used, always 1 [0:0]
+ UINT8 CRC: 7; // CRC [7:1]
+
+ UINT8 RESERVED_1: 2; // Reserved [9:8]
+ UINT8 FILE_FORMAT: 2; // File format [11:10]
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]
+
+ UINT16 RESERVED_2: 5; // Reserved [20:16]
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]
+ UINT16 RESERVED_3: 2; // Reserved [30:29]
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]
+
+ UINT32 WP_GRP_SIZE: 7; // Write protect group size [38:32]
+ UINT32 SECTOR_SIZE: 7; // Erase sector size [45:39]
+ UINT32 ERASE_BLK_EN: 1; // Erase single block enable [46:46]
+ UINT32 C_SIZE_MULT: 3; // Device size multiplier [49:47]
+ UINT32 VDD_W_CURR_MAX: 3; // Max. write current @ VDD max [52:50]
+ UINT32 VDD_W_CURR_MIN: 3; // Max. write current @ VDD min [55:53]
+ UINT32 VDD_R_CURR_MAX: 3; // Max. read current @ VDD max [58:56]
+ UINT32 VDD_R_CURR_MIN: 3; // Max. read current @ VDD min [61:59]
+ UINT32 C_SIZELow2: 2; // Device size [63:62]
+
+ UINT32 C_SIZEHigh10: 10;// Device size [73:64]
+ UINT32 RESERVED_4: 2; // Reserved [75:74]
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]
+ UINT32 READ_BL_LEN: 4; // Max. read data block length [83:80]
+ UINT32 CCC: 12;// Card command classes [95:84]
+
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+ UINT8 TAAC ; // Data read access-time 1 [119:112]
+
+ UINT8 RESERVED_5: 6; // Reserved [125:120]
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
+}CSD;
+
+
+
+typedef struct {
+ UINT8 NOT_USED: 1; // Not used, always 1 [0:0]
+ UINT8 CRC: 7; // CRC [7:1]
+ UINT8 RESERVED_1: 2; // Reserved [9:8]
+ UINT8 FILE_FORMAT: 2; // File format [11:10]
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]
+ UINT16 RESERVED_2: 5; // Reserved [20:16]
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]
+ UINT16 RESERVED_3: 2; // Reserved [30:29]
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]
+ UINT16 WP_GRP_SIZE: 7; // Write protect group size [38:32]
+ UINT16 SECTOR_SIZE: 7; // Erase sector size [45:39]
+ UINT16 ERASE_BLK_EN: 1; // Erase single block enable [46:46]
+ UINT16 RESERVED_4: 1; // Reserved [47:47]
+ UINT32 C_SIZELow16: 16;// Device size [69:48]
+ UINT32 C_SIZEHigh6: 6; // Device size [69:48]
+ UINT32 RESERVED_5: 6; // Reserved [75:70]
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]
+ UINT16 READ_BL_LEN: 4; // Max. read data block length [83:80]
+ UINT16 CCC: 12;// Card command classes [95:84]
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+ UINT8 TAAC ; // Data read access-time 1 [119:112]
+ UINT8 RESERVED_6: 6; // 0 [125:120]
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
+}CSD_SDV2;
+
+typedef enum {
+ UNKNOWN_CARD,
+ MMC_CARD, //MMC card
+ SD_CARD, //SD 1.1 card
+ SD_CARD_2, //SD 2.0 or above standard card
+ SD_CARD_2_HIGH, //SD 2.0 or above high capacity card
+ SD_CARD_MAX
+} CARD_TYPE;
+
+
+
+typedef enum {
+ MSHC_IDMA,
+ MSHC_FIFO
+}MSHC_OPERATION_MODE;
+
+typedef struct {
+ UINT16 RCA;
+ UINTN BlockSize;
+ UINTN NumBlocks;
+ UINTN ClockFrequencySelect;
+ CARD_TYPE CardType;
+ OCR OCRData;
+ CID CIDData;
+ CSD CSDData;
+} CARD_INFO;
+
+
+EFI_STATUS
+DetectCard (VOID);
+void mshci_reset_fifo(void);
+
+extern EFI_BLOCK_IO_PROTOCOL gBlockIo;
+
+#endif
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.inf
new file mode 100755
index 000000000..167eee6a4
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.inf
@@ -0,0 +1,58 @@
+#/** @file
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = SDHCDxe
+ FILE_GUID = 7B857F59-CD4D-4403-A866-CFAD3A7C1381
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = SDHCInitialize
+
+
+[Sources.common]
+ SDHCDxe.c
+ SDHCDxe_5250.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+ SamsungPlatformPkg/SamsungPlatformPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ IoLib
+ TimerLib
+ MemoryAllocationLib
+ UefiLib
+
+[Guids]
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gSamsungPlatformGpioProtocolGuid ## GPIO Protocol
+ gEfiEblAddCommandProtocolGuid
+
+
+[Pcd]
+ gExynosPkgTokenSpaceGuid.PcdCmuBase
+ gExynosPkgTokenSpaceGuid.PcdSdMmcBase
+ gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferBase
+
+[Depex]
+ TRUE
+
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_5250.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_5250.c
new file mode 100755
index 000000000..5408360b0
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_5250.c
@@ -0,0 +1,658 @@
+/** @file
+ MMC/SD Card driver for Secure Digital Host Controller
+
+ This driver always produces a BlockIo protocol but it starts off with no Media
+ present. A TimerCallBack detects when media is inserted or removed and after
+ a media change event a call to BlockIo ReadBlocks/WriteBlocks will cause the
+ media to be detected (or removed) and the BlockIo Media structure will get
+ updated. No MMC/SD Card harward registers are updated until the first BlockIo
+ ReadBlocks/WriteBlocks after media has been insterted (booting with a card
+ plugged in counts as an insertion event).
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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/TimerLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/ExynosGpio.h>
+#include <Platform/ArmPlatform.h>
+#include <Platform/Exynos5250.h>
+#include <Platform/Arndale5250.h>
+
+
+#include "SDHCDxe.h"
+
+//#undef EFI_D_INFO
+//#define EFI_D_INFO 1
+
+
+
+void MSHC_reset_all(void)
+{
+ int count;
+ volatile int ctl_val=0;
+ UINT32 SdMmcBaseAddr;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ /* Wait max 100 ms */
+ count = 10000;
+
+ /* before reset ciu, it should check DATA0. if when DATA0 is low and
+ it resets ciu, it might make a problem */
+ while ((MmioRead32 ((SdMmcBaseAddr + MSHCI_STATUS)) & (1<<9))){
+ if (count == 0) {
+ DEBUG ((EFI_D_ERROR, "MMC controller never released. \n"));
+ return;
+ }
+ count--;
+ MicroSecondDelay(1);
+ }
+
+ // Reset CIU
+ ctl_val = MmioRead32((SdMmcBaseAddr + MSHCI_CTRL));
+ ctl_val |= CTRL_RESET;
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), ctl_val);
+
+ //Reset FIFO
+ MSHC_reset_fifo();
+
+ //Reset DMA
+ ctl_val = MmioRead32((SdMmcBaseAddr + MSHCI_CTRL));
+ ctl_val |= DMA_RESET;
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), ctl_val);
+
+ //Set auto stop CMD
+ ctl_val = MmioRead32((SdMmcBaseAddr + MSHCI_CTRL));
+ ctl_val |= SEND_AS_CCSD;
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), ctl_val);
+
+}
+
+
+void MSHC_Set_DDR(int BusMode)
+{
+
+ UINT32 clkphase;
+ //clkphase = 0x03030002; //cmd response error at 50M RINT=0x46 error, RE and CD, RCRC
+ //clkphase = 0x03020001; //data read error at 50M SBE
+ UINT32 SdMmcBaseAddr;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ if(BusMode==BUSMODE_DDR)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC DDR .\n"));
+ MmioWrite32((SdMmcBaseAddr + MSHCI_UHS_REG), UHS_DDR);
+ clkphase = 0x03020001;
+ }
+ else
+ {
+ DEBUG ((EFI_D_INFO, "MSHC Non DDR .\n"));
+ MmioWrite32((SdMmcBaseAddr + MSHCI_UHS_REG), UHS_NON_DDR);
+ clkphase = 0x03030002;
+ }
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CLKSEL), clkphase);
+
+}
+
+
+void MSHC_5250_init(void)
+{
+ UINT32 SdMmcBaseAddr;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ /* Power Enable Register */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_PWREN), POWER_ENABLE);
+ //MSHC_Set_DDR(BUSMODE_DDR);
+
+ MSHC_reset_all();
+
+ // Initialize FIFO
+ MmioWrite32((SdMmcBaseAddr + MSHCI_FIFOTH), (MSIZE_8 | TX_WMARK_DEFAULT | RX_WMARK_DEFAULT));
+
+ /* It clears all pending interrupts */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_RINTSTS), INTMSK_ALL);
+ /* It dose not use Interrupt. Disable all */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_INTMSK), 0);
+
+ //UpdateMSHCClkFrequency(MSHC_CLK_400);
+
+ /* Set auto stop command */
+ //MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), (1<<10));
+
+ /* set debounce filter value*/
+ MmioWrite32((SdMmcBaseAddr + MSHCI_DEBNCE), (0xfffff));
+
+ /* clear card type. set 1-bit mode */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTYPE), 0x0);
+
+ /* set bus mode register for IDMAC */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_BMOD), (BMOD_IDMAC_RESET));
+
+ /* disable all interrupt source of IDMAC */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_IDINTEN), (0x0));
+
+ /* set max timeout */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_TMOUT), (0xffffffff));
+
+ MmioWrite32((SdMmcBaseAddr + MSHCI_BLKSIZ), BLEN_512BYTES);
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CLKSEL), 0x03030002);
+
+}
+
+EFI_STATUS
+InitializeMSHC (
+ VOID
+ )
+{
+
+ EFI_STATUS Status;
+ EXYNOS_GPIO *Gpio;
+ UINT32 CumBaseAddr;
+ //UINT32 SdMmcBaseAddr;
+ UINT32 i, clock;
+ volatile UINT32 ctl_val;
+
+
+ Status = gBS->LocateProtocol(&gSamsungPlatformGpioProtocolGuid, NULL, (VOID **)&Gpio);
+ ASSERT_EFI_ERROR(Status);
+
+ CumBaseAddr = PcdGet32(PcdCmuBase);
+ //SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ //MmioWrite32((SdMmcBaseAddr + SDHC_SWRST_OFFSET), SRA);
+
+ // Set Clock Source for using MPLL
+ ctl_val = MmioRead32((CumBaseAddr + CLK_SRC_FSYS_OFFSET));
+ ctl_val &= ~(0xf<<8);
+ ctl_val |= (0x6<<8);
+ MmioWrite32((CumBaseAddr + CLK_SRC_FSYS_OFFSET), ctl_val);
+ //MmioAndThenOr32 ((CumBaseAddr + CLK_SRC_FSYS_OFFSET), ~(0xF), (0x6));
+
+ // CLK mask
+ ctl_val = MmioRead32((CumBaseAddr + CLK_SRC_MASK_FSYS_OFFSET));
+ ctl_val |= (0x1<<8);
+ MmioWrite32((CumBaseAddr + CLK_SRC_MASK_FSYS_OFFSET), ctl_val);
+
+ // CLK gating
+ ctl_val = MmioRead32((CumBaseAddr + CLK_GATE_IP_FSYS_OFFSET));
+ ctl_val |= (0x1<<14);
+ MmioWrite32((CumBaseAddr + CLK_GATE_IP_FSYS_OFFSET), ctl_val);
+
+
+ /* MMC2 clock div */
+ clock = 800; //MPLL in MHz
+ for(i=0; i<= 0xf; i++)
+ {
+ if((clock / (i+1)) <= 90) {
+ MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS2_OFFSET), ~(0xF << 0), (i << 0));
+ break;
+ }
+ }
+
+
+ // 2. GPIO setting
+ // Set GPIO for using SDMMC2
+ Gpio->Set(Gpio,SD_2_EVT1_CLK,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_2_EVT1_CMD,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_2_EVT1_CDn,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_2_EVT1_DATA0,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_2_EVT1_DATA1,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_2_EVT1_DATA2,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_2_EVT1_DATA3,GPIO_MODE_SPECIAL_FUNCTION_2);
+
+ Gpio->SetPull(Gpio,SD_2_EVT1_CLK,GPIO_PULL_NONE);
+ Gpio->SetPull(Gpio,SD_2_EVT1_CMD,GPIO_PULL_NONE);
+ Gpio->SetPull(Gpio,SD_2_EVT1_CDn,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_2_EVT1_DATA0,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_2_EVT1_DATA1,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_2_EVT1_DATA2,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_2_EVT1_DATA3,GPIO_PULL_UP);
+
+ Gpio->SetStrength(Gpio,SD_2_EVT1_CLK,GPIO_DRV_4X);
+ Gpio->SetStrength(Gpio,SD_2_EVT1_CMD,GPIO_DRV_4X);
+ Gpio->SetStrength(Gpio,SD_2_EVT1_CDn,GPIO_DRV_4X);
+ Gpio->SetStrength(Gpio,SD_2_EVT1_DATA0,GPIO_DRV_4X);
+ Gpio->SetStrength(Gpio,SD_2_EVT1_DATA1,GPIO_DRV_4X);
+ Gpio->SetStrength(Gpio,SD_2_EVT1_DATA2,GPIO_DRV_4X);
+ Gpio->SetStrength(Gpio,SD_2_EVT1_DATA3,GPIO_DRV_4X);
+
+ MSHC_5250_init();
+ return EFI_SUCCESS;
+}
+
+void MSHC_reset_fifo(void)
+{
+ volatile int ctl_val=0;
+ UINT32 SdMmcBaseAddr;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+ //Reset FIFO
+ ctl_val = MmioRead32((SdMmcBaseAddr + MSHCI_CTRL));
+ ctl_val |= FIFO_RESET;
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), ctl_val);
+
+}
+
+
+VOID MSHC_clock_onoff (int value)
+{
+ volatile UINT32 loop_count = 0x100000;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ if(value==CLK_ENABLE)
+ {
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKENA), (0x1<<0));
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), 0);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), CMD_ONLY_CLK);
+ do {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_CMD) & CMD_STRT_BIT)==0)
+ break;
+ loop_count--;
+ } while (loop_count);
+ }
+ else
+ {
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKENA), (0x0<<0));
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), 0);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), CMD_ONLY_CLK);
+ do {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_CMD) & CMD_STRT_BIT)==0)
+ break;
+ loop_count--;
+ } while (loop_count);
+ }
+
+ if (loop_count == 0) {
+ DEBUG ((EFI_D_ERROR, "MSHC::clockonoff : Clk = %d\n", value));
+ }
+
+}
+
+
+VOID
+UpdateMSHCClkFrequency (
+ UINTN NewCLK
+ )
+{
+ UINT32 CumBaseAddr;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+ CumBaseAddr = PcdGet32(PcdCmuBase);
+
+ // Disable all clocks to not provide the clock to the card
+//(CONFIG_CPU_EXYNOS5250_EVT1)
+ MSHC_clock_onoff(CLK_DISABLE);
+ //MmioAnd32 ((SdMmcBaseAddr + CLKCON_OFFSET), ~(0xF));
+
+ //Set new clock frequency.
+ if (NewCLK == MSHC_CLK_400)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::CLK=400.\n"));
+ // MPLL=800, cclk_in=100, 100M/250=400k
+ //MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS1_OFFSET), ~(0xFFFF), 0xE008);
+ MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS2_OFFSET), ~(0xFFFF), 0x1);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKDIV), 125);
+ }
+ else if (NewCLK == MSHC_CLK_25M)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::CLK=25M.\n"));
+ // DDR mode use CLKDIV MPLL = 800, SCLK = 400, cclk_in=100M
+ //MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS2_OFFSET), ~(0xFFFF), 0x1);
+ //MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKDIV), 2);
+ MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS2_OFFSET), ~(0xFFFF), 0x1);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKDIV), 2);
+ }
+ else if(NewCLK == MSHC_CLK_50M)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::CLK=50M.\n"));
+ // DDR mode use CLKDIV MPLL = 800, SCLK = 400, cclk_in=100M
+ MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS2_OFFSET), ~(0xFFFF), 0x1);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKDIV), 1);
+
+ MSHC_Set_DDR(BUSMODE_DDR);
+ //MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), CMD_ONLY_CLK);
+ }
+
+//#if defined(CONFIG_CPU_EXYNOS5250_EVT1)
+ MSHC_clock_onoff(CLK_ENABLE);
+ //MmioOr32 ((SdMmcBaseAddr + CLKCON_OFFSET), ICE);
+
+ //Poll till Internal Clock Stable
+ //while ((MmioRead32 ((SdMmcBaseAddr + CLKCON_OFFSET)) & ICS) != ICS);
+
+ //Set Clock enable to 0x1 to provide the clock to the card
+ //MmioOr32 ((SdMmcBaseAddr + CLKCON_OFFSET), CCE);
+
+}
+
+extern MSHC_OPERATION_MODE MSHC_operation_mode;
+void mshci_set_mdma_desc(UINT8 *desc_vir, UINT8 *desc_phy,
+ UINT32 des0, UINT32 des1, UINT32 des2)
+{
+ ((struct mshci_idmac *)(desc_vir))->des0 = des0;
+ ((struct mshci_idmac *)(desc_vir))->des1 = des1;
+ ((struct mshci_idmac *)(desc_vir))->des2 = des2;
+ ((struct mshci_idmac *)(desc_vir))->des3 = (UINT32)desc_phy +
+ sizeof(struct mshci_idmac);
+}
+
+
+VOID
+PrepareTransfer (
+IN OUT VOID *Buffer, UINTN BlockCount, IN OPERATION_TYPE OperationType
+ )
+{
+ UINT32 SdMmcBaseAddr;
+ UINT32 EmmcDMABufferBase;
+ volatile UINT32 MshcRegValue;
+ struct mshci_idmac *pdesc_dmac;
+ UINT32 des_flag;
+ UINTN i=0;
+ UINT32 ByteCnt=0;
+ UINT32 BlockCnt=BlockCount;
+// UINT32 MSH_uDES_A_0, MSH_uDES_A_1, MSH_uDES_A_2, MSH_uDES_A_3;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+ EmmcDMABufferBase = PcdGet32(PcdEmmcDMABufferBase);
+ EmmcDMABufferBase += PHY_CH2_OFFSET;
+ DEBUG ((EFI_D_INFO, "EmmcDMABufferBase:0x%x \n", EmmcDMABufferBase));
+ pdesc_dmac = (struct mshci_idmac *)EmmcDMABufferBase;
+
+ if(MSHC_operation_mode==MSHC_FIFO)
+ {
+ MSHC_reset_fifo();
+
+ // 1. enable interrupt mode
+ MshcRegValue = MmioRead32(SdMmcBaseAddr + MSHCI_CTRL);
+ MshcRegValue |= INT_ENABLE;
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CTRL), MshcRegValue);
+
+ // 2. DDR mode
+
+ // 3. set BLKSIZE
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BLKSIZ), BLEN_512BYTES);
+ //MmioWrite32 ((SdMmcBaseAddr + MSHCI_BLKSIZ), BLKSIZE_1);
+
+ // 4. set BYTCNT
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BYTCNT), BLEN_512BYTES);
+
+ //Setting Data timeout counter value to max value.
+ MmioWrite32((SdMmcBaseAddr + MSHCI_TMOUT), (0xffffffff));
+
+ }
+ else if(MSHC_operation_mode==MSHC_IDMA)
+ {
+ ZeroMem ((VOID *)EmmcDMABufferBase, PHY_BUF_OFFSET);//20120608
+ if(OperationType==WRITE)
+ {
+ CopyMem((VOID *)(EmmcDMABufferBase+PHY_BUF_OFFSET), (VOID *)Buffer, BlockCount*BLEN_512BYTES);
+ //DEBUG ((EFI_D_INFO, "MSHC_DMA prepare WRITE:%d Block \n", BlockCount));
+ }
+ else
+ {
+ //DEBUG ((EFI_D_INFO, "MSHC_DMA prepare READ:%d Block \n", BlockCount));
+ }
+
+ MSHC_reset_fifo();
+
+ //IDMA reset
+ MshcRegValue = MmioRead32(SdMmcBaseAddr + MSHCI_BMOD);
+ MshcRegValue |= (BMOD_IDMAC_RESET);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BMOD), MshcRegValue);
+
+
+ // 1. enable IDMA at CTRL
+ MshcRegValue = MmioRead32(SdMmcBaseAddr + MSHCI_CTRL);
+ MshcRegValue &= ~(INT_ENABLE);
+ MshcRegValue |= (ENABLE_IDMAC);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CTRL), MshcRegValue);
+
+
+ // 2. enable IDMA at BMODE
+ //Set Block Size and Block count.
+ MshcRegValue = MmioRead32(SdMmcBaseAddr + MSHCI_BMOD);
+ MshcRegValue |= (BMOD_IDMAC_ENABLE | BMOD_IDMAC_FB);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BMOD), MshcRegValue);
+
+ // interrupt enable
+ MmioWrite32((SdMmcBaseAddr + MSHCI_IDINTEN), (0x337));
+
+ for(i=0; ; i++)
+ {
+ // set descriptor multichain
+ des_flag = (MSHCI_IDMAC_OWN|MSHCI_IDMAC_CH);
+ des_flag |= (i==0) ? MSHCI_IDMAC_FS:0;
+ if(BlockCnt<=8)
+ {
+ //DEBUG ((EFI_D_INFO, "DESC LD\n"));
+ des_flag |= (MSHCI_IDMAC_LD);
+ mshci_set_mdma_desc((UINT8 *)pdesc_dmac,
+ //(UINT8 *)pdesc_dmac,
+ (UINT8 *)(EmmcDMABufferBase-sizeof(struct mshci_idmac)),
+ des_flag, BlockCnt*BLEN_512BYTES,
+ ((UINT32)((EmmcDMABufferBase + PHY_BUF_OFFSET)+(UINT32)(i*PHY_BUF_SIZE))));
+ break;
+
+ }
+ //DEBUG ((EFI_D_INFO, "DESC FS\n"));
+ mshci_set_mdma_desc((UINT8 *)pdesc_dmac,
+ (UINT8 *)pdesc_dmac,
+ des_flag, BLEN_512BYTES*8,
+ ((UINT32)((EmmcDMABufferBase + PHY_BUF_OFFSET)+(UINT32)(i*PHY_BUF_SIZE))));
+
+ BlockCnt -=8;
+ pdesc_dmac++;
+
+ }
+
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_DBADDR), (UINT32)EmmcDMABufferBase);
+
+ // 3. set BLKSIZE
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BLKSIZ), BLEN_512BYTES);
+
+ // 4. set BYTCNT
+ ByteCnt = (BlockCount*BLEN_512BYTES);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BYTCNT), ByteCnt);
+
+ //Setting Data timeout counter value to max value.
+ MmioWrite32((SdMmcBaseAddr + MSHCI_TMOUT), (0xffffffff));
+ DEBUG ((EFI_D_INFO, "Block:%d BYTCNT:0x%x ByteCnt:0x%x\n", BlockCount,MmioRead32(SdMmcBaseAddr + MSHCI_BYTCNT), ByteCnt));
+
+ }
+
+}
+
+EFI_STATUS MSHC_ReadFIFO(IN UINTN Size32, OUT VOID *Buffer)
+{
+ EFI_STATUS Status;
+ UINT32 SdMmcBaseAddr;
+ UINTN *DataBuffer = Buffer;
+ UINTN BufSize=Size32;
+ UINTN FifoCount=0;
+ UINTN Count=0;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+ //Check controller status to make sure there is no error.
+
+ while (BufSize)
+ {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & INTMSK_RXDR)
+ {
+
+ //Read block worth of data.
+ FifoCount = GET_FIFO_COUNT(MmioRead32 (SdMmcBaseAddr + MSHCI_STATUS));
+ DEBUG ((EFI_D_INFO, "MSHC::ReadBlock DTO FIFO:%d\n", FifoCount));
+ for (Count = 0; Count < FifoCount; Count++)
+ {
+ *DataBuffer++ = MmioRead32 (SdMmcBaseAddr + MSHCI_FIFO);
+ }
+ MmioWrite32((SdMmcBaseAddr + MSHCI_RINTSTS), INTMSK_RXDR);
+ BufSize -= FifoCount;
+ }
+
+ else if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & INTMSK_DTO)
+ {
+
+ //Read block worth of data.
+ FifoCount = GET_FIFO_COUNT(MmioRead32 (SdMmcBaseAddr + MSHCI_STATUS));
+ DEBUG ((EFI_D_INFO, "MSHC::ReadBlock DTO FIFO:%d\n", FifoCount));
+ for (Count = 0; Count < FifoCount; Count++)
+ {
+ *DataBuffer++ = MmioRead32 (SdMmcBaseAddr + MSHCI_FIFO);
+ }
+ MmioWrite32((SdMmcBaseAddr + MSHCI_RINTSTS), INTMSK_DTO);
+ BufSize -= FifoCount;
+ }
+
+ else if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & (INTMSK_DCRC|INTMSK_DRTO|INTMSK_HTO|INTMSK_FRUN))
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::ReadBlock Error RINT:0x%x\n", MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ }
+
+ if(BufSize==0)
+ {
+ Status = EFI_SUCCESS;
+ }
+ else
+ {
+ Status = EFI_BAD_BUFFER_SIZE;
+ }
+ return Status;
+}
+
+EFI_STATUS MSHC_WriteFIFO(IN UINTN Size32, IN VOID *Buffer)
+{
+ UINT32 SdMmcBaseAddr;
+ UINTN *DataBuffer = Buffer;
+ UINTN BufSize=Size32;
+ UINTN Count=0;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+
+ if(BufSize>FIFO_SIZE)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::Error MSHC_WriteFIFO Bad buffer size\n"));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ //Write block worth of data.
+ for (Count = 0; Count < BufSize; Count++)
+ {
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_FIFO), *DataBuffer++);
+ }
+ return EFI_SUCCESS;
+
+}
+
+/*typedef
+VOID
+CopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ );*/
+
+EFI_STATUS MSHC_ReadDMA(OUT VOID *Buffer, IN UINTN BlockCount)
+{
+ EFI_STATUS Status;
+ UINT32 SdMmcBaseAddr, EmmcDMABufferBase;
+ UINTN Count=MAX_RETRY_COUNT;
+ //UINT32 MshcRegValue;
+ //UINT32 TransferSize=0;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+ EmmcDMABufferBase = PcdGet32(PcdEmmcDMABufferBase);
+ EmmcDMABufferBase += PHY_CH2_OFFSET;
+ //Check controller status to make sure there is no error.
+
+ while (Count)
+ {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & INTMSK_DTO)
+ {
+ //TransferSize = MmioRead32 (SdMmcBaseAddr + MSHCI_TBBCNT);
+ CopyMem((VOID *)Buffer, (VOID *)(EmmcDMABufferBase+PHY_BUF_OFFSET), BlockCount*BLEN_512BYTES);
+ DEBUG ((EFI_D_INFO, "MSHC_ReadDMA Over %d Blocks\n", BlockCount));
+ break;
+ }
+ else if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & (DATA_ERR|DATA_TOUT))
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC_ReadDMA Err RINT:0x%x\n", MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)));
+ }
+
+ else
+ {
+ Count--;
+ MicroSecondDelay(1);
+ DEBUG ((EFI_D_INFO, ".\n"));
+ }
+
+ }
+
+ if(Count!=0)
+ {
+ Status = EFI_SUCCESS;
+ }
+ else
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC_ReadDMA bad buffer size RINT:0x%x\n", MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)));
+ Status = EFI_BAD_BUFFER_SIZE;
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_PLDMND), 7);
+
+ }
+ return Status;
+}
+
+EFI_STATUS MSHC_WriteDMA(IN VOID *Buffer, IN UINTN BlockCount)
+{
+ EFI_STATUS Status;
+ UINT32 SdMmcBaseAddr;
+ UINTN Count=MAX_RETRY_COUNT;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcBase);
+ //Check controller status to make sure there is no error.
+
+ while (Count)
+ {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & INTMSK_DTO)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC_writeDMA Over %d blocks\n", BlockCount));
+ break;
+ }
+ else
+ {
+ MicroSecondDelay(1);
+ Count--;
+ }
+
+ }
+
+ if(Count!=0)
+ {
+ Status = EFI_SUCCESS;
+ }
+ else
+ {
+ Status = EFI_BAD_BUFFER_SIZE;
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_PLDMND), 7);
+ DEBUG ((EFI_D_ERROR, "MSHC_writeDMA bad buffer size RINT:0x%x \n", MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)));
+ }
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_5250.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_5250.h
new file mode 100755
index 000000000..7dbf590e1
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_5250.h
@@ -0,0 +1,323 @@
+/** @file
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 _MSHCDXE_5250_H_
+#define _MSHCDXE_5250_H_
+
+
+/*
+ * Controller registers
+ */
+/*****************************************************/
+/* MSHC Internal Registers */
+/*****************************************************/
+
+#define MSHCI_CTRL 0x00 /* Control */
+#define MSHCI_PWREN 0x04 /* Power-enable */
+#define MSHCI_CLKDIV 0x08 /* Clock divider */
+#define MSHCI_CLKSRC 0x0C /* Clock source */
+#define MSHCI_CLKENA 0x10 /* Clock enable */
+#define MSHCI_TMOUT 0x14 /* Timeout */
+#define MSHCI_CTYPE 0x18 /* Card type */
+#define MSHCI_BLKSIZ 0x1C /* Block Size */
+#define MSHCI_BYTCNT 0x20 /* Byte count */
+#define MSHCI_INTMSK 0x24 /* Interrupt Mask */
+#define MSHCI_CMDARG 0x28 /* Command Argument */
+#define MSHCI_CMD 0x2C /* Command */
+#define MSHCI_RESP0 0x30 /* Response 0 */
+#define MSHCI_RESP1 0x34 /* Response 1 */
+#define MSHCI_RESP2 0x38 /* Response 2 */
+#define MSHCI_RESP3 0x3C /* Response 3 */
+#define MSHCI_MINTSTS 0x40 /* Masked interrupt status */
+#define MSHCI_RINTSTS 0x44 /* Raw interrupt status */
+#define MSHCI_STATUS 0x48 /* Status */
+#define MSHCI_FIFOTH 0x4C /* FIFO threshold */
+#define MSHCI_CDETECT 0x50 /* Card detect */
+#define MSHCI_WRTPRT 0x54 /* Write protect */
+#define MSHCI_GPIO 0x58 /* General Purpose IO */
+#define MSHCI_TCBCNT 0x5C /* Transferred CIU byte count */
+#define MSHCI_TBBCNT 0x60 /* Transferred host/DMA to/from byte count */
+#define MSHCI_DEBNCE 0x64 /* Card detect debounce */
+#define MSHCI_USRID 0x68 /* User ID */
+#define MSHCI_VERID 0x6C /* Version ID */
+#define MSHCI_HCON 0x70 /* Hardware Configuration */
+#define MSHCI_UHS_REG 0x74 /* UHS and DDR setting */
+#define MSHCI_BMOD 0x80 /* Bus mode register */
+#define MSHCI_PLDMND 0x84 /* Poll demand */
+#define MSHCI_DBADDR 0x88 /* Descriptor list base address */
+#define MSHCI_IDSTS 0x8C /* Internal DMAC status */
+#define MSHCI_IDINTEN 0x90 /* Internal DMAC interrupt enable */
+#define MSHCI_DSCADDR 0x94 /* Current host descriptor address */
+#define MSHCI_BUFADDR 0x98 /* Current host buffer address */
+#define MSHCI_CLKSEL 0x9C /* Drv/sample clock selection register */
+#define MSHCI_WAKEUPCON 0xA0 /* Wakeup control register */
+#define MSHCI_CLOCKCON 0xA4 /* Clock (delay) control register */
+#define MSHCI_FIFO 0x200
+#define MSHCI_FIFODAT(x) (x) /* FIFO data read write */
+
+
+/*****************************************************
+ * Control Register Register
+ * MSHCI_CTRL - offset 0x00
+ *****************************************************/
+
+#define CTRL_RESET (0x1<<0) /* Reset DWC_mobile_storage controller */
+#define FIFO_RESET (0x1<<1) /* Reset FIFO */
+#define DMA_RESET (0x1<<2) /* Reset DMA interface */
+#define INT_ENABLE (0x1<<4) /* Global interrupt enable/disable bit */
+#define DMA_ENABLE (0x1<<5) /* DMA transfer mode enable/disable bit */
+#define READ_WAIT (0x1<<6) /* For sending read-wait to SDIO cards */
+#define SEND_IRQ_RESP (0x1<<7) /* Send auto IRQ response */
+#define ABRT_READ_DATA (0x1<<8)
+#define SEND_CCSD (0x1<<9)
+#define SEND_AS_CCSD (0x1<<10)
+#define CEATA_INTSTAT (0x1<<11)
+#define CARD_VOLA (0xF<<16)
+#define CARD_VOLB (0xF<<20)
+#define ENABLE_OD_PULLUP (0x1<<24)
+#define ENABLE_IDMAC (0x1<<25)
+#define MSHCI_RESET_ALL (0x1)
+
+/*****************************************************
+ * Power Enable Register
+ * MSHCI_PWREN - offset 0x04
+ *****************************************************/
+#define POWER_ENABLE (0x1<<0)
+
+/*****************************************************
+* Clock Enable Register
+* MSHCI_CLKENA - offset 0x10
+*****************************************************/
+#define CLK_SDMMC_MAX (48000000) /* 96Mhz. it SHOULDBE optimized */
+#define CLK_ENABLE (0x1<<0)
+#define CLK_DISABLE (0x0<<0)
+
+
+/*****************************************************
+ * Interrupt Mask Register
+ * MSHCI_INTMSK - offset 0x24
+ *****************************************************/
+#define INT_MASK (0xFFFF<<0)
+#define SDIO_INT_MASK (0xFFFF<<16)
+#define SDIO_INT_ENABLE (0x1<<16)
+
+/* interrupt bits */
+#define INTMSK_ALL 0xFFFFFFFF
+#define INTMSK_CDETECT (0x1<<0)
+#define INTMSK_RE (0x1<<1)
+#define INTMSK_CDONE (0x1<<2)
+#define INTMSK_DTO (0x1<<3)
+#define INTMSK_TXDR (0x1<<4)
+#define INTMSK_RXDR (0x1<<5)
+#define INTMSK_RCRC (0x1<<6)
+#define INTMSK_DCRC (0x1<<7)
+#define INTMSK_RTO (0x1<<8)
+#define INTMSK_DRTO (0x1<<9)
+#define INTMSK_HTO (0x1<<10)
+#define INTMSK_FRUN (0x1<<11)
+#define INTMSK_HLE (0x1<<12)
+#define INTMSK_SBE (0x1<<13)
+#define INTMSK_ACD (0x1<<14)
+#define INTMSK_EBE (0x1<<15)
+#define INTMSK_DMA (INTMSK_ACD|INTMSK_RXDR|INTMSK_TXDR)
+
+#define INT_SRC_IDMAC (0x0)
+#define INT_SRC_MINT (0x1)
+
+
+/*****************************************************
+ * Command Register
+ * MSHCI_CMD - offset 0x2C
+ *****************************************************/
+
+#define CMD_RESP_EXP_BIT (0x1<<6)
+#define CMD_RESP_LENGTH_BIT (0x1<<7)
+#define CMD_CHECK_CRC_BIT (0x1<<8)
+#define CMD_DATA_EXP_BIT (0x1<<9)
+#define CMD_RW_BIT (0x1<<10)
+#define CMD_TRANSMODE_BIT (0x1<<11)
+#define CMD_SENT_AUTO_STOP_BIT (0x1<<12)
+#define CMD_WAIT_PRV_DAT_BIT (0x1<<13)
+#define CMD_ABRT_CMD_BIT (0x1<<14)
+#define CMD_SEND_INIT_BIT (0x1<<15)
+#define CMD_CARD_NUM_BITS (0x1F<<16)
+#define CMD_SEND_CLK_ONLY (0x1<<21)
+#define CMD_READ_CEATA (0x1<<22)
+#define CMD_CCS_EXPECTED (0x1<<23)
+#define CMD_USE_HOLD_REG (0x1<<29)
+#define CMD_STRT_BIT (0x1<<31)
+#define CMD_ONLY_CLK (CMD_STRT_BIT | CMD_SEND_CLK_ONLY | \
+ CMD_WAIT_PRV_DAT_BIT)
+
+/*****************************************************
+ * Raw Interrupt Register
+ * MSHCI_RINTSTS - offset 0x44
+ *****************************************************/
+#define INT_STATUS (0xFFFF<<0)
+#define SDIO_INTR (0xFFFF<<16)
+#define DATA_ERR (INTMSK_EBE|INTMSK_SBE|INTMSK_HLE|INTMSK_FRUN |\
+ INTMSK_EBE |INTMSK_DCRC)
+#define DATA_TOUT (INTMSK_HTO|INTMSK_DRTO)
+#define DATA_STATUS (DATA_ERR|DATA_TOUT|INTMSK_RXDR|INTMSK_TXDR|INTMSK_DTO)
+#define CMD_STATUS (INTMSK_RTO|INTMSK_RCRC|INTMSK_CDONE|INTMSK_RE)
+#define CMD_ERROR (INTMSK_RCRC|INTMSK_RTO|INTMSK_RE)
+
+
+/*****************************************************
+ * Status Register
+ * MSHCI_STATUS - offset 0x48
+ *****************************************************/
+#define FIFO_RXWTRMARK (0x1<<0)
+#define FIFO_TXWTRMARK (0x1<<1)
+#define FIFO_EMPTY (0x1<<2)
+#define FIFO_FULL (0x1<<3)
+#define CMD_FSMSTAT (0xF<<4)
+#define DATA_3STATUS (0x1<<8)
+#define DATA_BUSY (0x1<<9)
+#define DATA_MCBUSY (0x1<<10)
+#define RSP_INDEX (0x3F<<11)
+#define FIFO_COUNT (0x1FFF<<17)
+#define DMA_ACK (0x1<<30)
+#define DMA_REQ (0x1<<31)
+#define FIFO_WIDTH (0x4)
+#define FIFO_DEPTH (0x20)
+#define FIFO_SIZE (0x80)
+#define GET_FIFO_COUNT(x) (((x)&0x3ffe0000)>>17)
+
+
+
+/*****************************************************
+ * FIFO Threshold Watermark Register
+ * MSHCI_FIFOTH - offset 0x4C
+ *****************************************************/
+#define TX_WMARK (0xFFF<<0)
+#define RX_WMARK (0xFFF<<16)
+#define MSIZE_MASK (0x7<<28)
+
+/* DW DMA Mutiple Transaction Size */
+#define MSIZE_1 (0<<28)
+#define MSIZE_4 (1<<28)
+#define MSIZE_8 (2<<28)
+#define MSIZE_16 (3<<28)
+#define MSIZE_32 (4<<28)
+#define MSIZE_64 (5<<28)
+#define MSIZE_128 (6<<28)
+#define MSIZE_256 (7<<28)
+
+#define TX_WMARK_DEFAULT (0x10<<0)
+#define RX_WMARK_DEFAULT (0x10<<16)
+
+//#define TX_WMARK_DEFAULT (0x40<<0)
+//#define RX_WMARK_DEFAULT (0x3F<<16)
+
+
+/*****************************************************
+ * Bus Mode Register
+ * MSHCI_UHS_REG - offset 0x74
+ *****************************************************/
+#define UHS_DDR (0x1<<16)
+#define UHS_NON_DDR (0x0<<16)
+#define BUSMODE_DDR 1
+#define BUSMODE_NON_DDR 0
+
+/*****************************************************
+ * Bus Mode Register
+ * MSHCI_BMOD - offset 0x80
+ *****************************************************/
+#define BMOD_IDMAC_RESET (0x1<<0)
+#define BMOD_IDMAC_FB (0x1<<1)
+#define BMOD_IDMAC_ENABLE (0x1<<7)
+
+/*****************************************************
+ * Hardware Configuration Register
+ * MSHCI_IDSTS - offset 0x8c
+ *****************************************************/
+#define IDSTS_FSM (0xf<<13)
+#define IDSTS_EB (0x7<<10)
+#define IDSTS_AIS (0x1<<9)
+#define IDSTS_NIS (0x1<<8)
+#define IDSTS_CES (0x1<<5)
+#define IDSTS_DU (0x1<<4)
+#define IDSTS_FBE (0x1<<2)
+#define IDSTS_RI (0x1<<1)
+#define IDSTS_TI (0x1<<0)
+
+
+/*****************************************************
+ * Card Type Register
+ * MSHCI_CTYPE - offset 0x18
+ *****************************************************/
+#define CARD_WIDTH14 (0xFFFF<<0)
+#define CARD_WIDTH8 (0xFFFF<<16)
+
+struct mshci_idmac {
+ UINT32 des0;
+ UINT32 des1;
+ UINT32 des2;
+ UINT32 des3;
+#define MSHCI_IDMAC_OWN (1<<31)
+#define MSHCI_IDMAC_ER (1<<5)
+#define MSHCI_IDMAC_CH (1<<4)
+#define MSHCI_IDMAC_FS (1<<3)
+#define MSHCI_IDMAC_LD (1<<2)
+#define MSHCI_IDMAC_DIC (1<<1)
+#define INTMSK_IDMAC_ALL (0x337)
+#define INTMSK_IDMAC_ERROR (0x214)
+};
+
+typedef enum {
+ READ,
+ WRITE
+} OPERATION_TYPE;
+
+
+/*****************************************************
+ * DMA Buffer structure
+ *
+ * CH0 for eMMC 0x40300000--0x40380000
+ * CH2 for SD Card 0x40380000--0x40400000
+ *****************************************************/
+#define EMMC_DMA_PHYSICAL_BUFFER_BASE 0x40300000
+#define EMMC_DMA_PHYSICAL_BUFFER_SIZE 0x00100000 //1MB
+#define PHY_CH2_OFFSET 0x80000
+#define PHY_BUF_OFFSET 0x1000 //4K
+#define PHY_BUF_SIZE 0x1000 //4K
+
+//#define MAX_MSHC_TRANSFER_SIZE 0x4000 //16K
+#define MAX_MSHC_TRANSFER_SIZE 0x40000 //512blocks, 256KB
+
+
+
+
+/*****************************************************
+ * External Functions
+ *****************************************************/
+
+
+EFI_STATUS InitializeMSHC (VOID);
+VOID UpdateMSHCClkFrequency (UINTN NewCLK);
+void MSHC_reset_fifo(void);
+extern void MSHC_reset_all(void);
+extern VOID PrepareTransfer (IN OUT VOID *Buffer, UINTN ByteCount, IN OPERATION_TYPE OperationType);
+extern EFI_STATUS MSHC_ReadFIFO(IN UINTN Size32, OUT VOID *Buffer);
+extern EFI_STATUS MSHC_WriteFIFO(IN UINTN Size32, IN VOID *Buffer);
+void mshci_set_mdma_desc(UINT8 *desc_vir, UINT8 *desc_phy,
+ UINT32 des0, UINT32 des1, UINT32 des2);
+EFI_STATUS MSHC_ReadDMA(OUT VOID *Buffer, IN UINTN BlockCount);
+EFI_STATUS MSHC_WriteDMA(IN VOID *Buffer, IN UINTN BlockCount);
+
+
+
+#endif
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_CMD.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_CMD.h
new file mode 100755
index 000000000..cbaa7b935
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe_CMD.h
@@ -0,0 +1,165 @@
+/** @file
+
+ Copyright (c) 2011, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 _MSHCDXE_CMD_H_
+#define _MSHCDXE_CMD_H_
+
+
+
+#define HosttoCard 0x1
+#define CardtoHost 0x0
+
+#define ENDMA BIT0
+#define ENBLKCNT BIT1
+#define RD1WT0 BIT4
+#define MUL1SIN0 BIT5
+#define RSPTYP136 (0x1 << 16)
+#define RSPTYP48 (0x2 << 16)
+#define RSPTYP48B (0x3 << 16)
+#define ENCMDCRC BIT19
+#define ENCMDIDX BIT20
+#define DATAPRNT BIT21
+
+
+#define CMDCOMP BIT0
+#define TRNSCOMP BIT1
+#define RDYFORWT BIT4
+#define RDYFORRD BIT5
+#define CARDINSERT BIT6
+#define CARDREMOVE BIT7
+#define ERRINT BIT15
+#define CMDTOUTERR BIT16
+#define CMDCRCERR BIT17
+#define CMDEBITERR BIT18
+#define CMDIDXERR BIT19
+#define DATATOUTERR BIT20
+#define DATACRCERR BIT21
+#define DATAEBITERR BIT22
+
+#define HCS BIT30 //Host capacity support/1 = Supporting high capacity
+
+
+
+/* Command Definitions */
+#define INDX(CMD_INDX) (CMD_INDX & 0x3F)
+
+#define CMD0 INDX(0)
+#define CMD0_INT_EN (CMDCOMP | CMDEBITERR)
+
+#define CMD1 (INDX(1) | RSPTYP48)
+#define CMD1_INT_EN (CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD2 (INDX(2) | ENCMDCRC | RSPTYP136)
+#define CMD2_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD3 (INDX(3) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD3_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD5 (INDX(5) | RSPTYP48)
+#define CMD5_INT_EN (CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD7 (INDX(7) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD7_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+//#define CMD8 (INDX(8) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD8 (INDX(8) | ENCMDIDX | RSPTYP48)
+#define CMD8_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+//Reserved(0)[12:31], Supply voltage(1)[11:8], check pattern(0xCE)[7:0] = 0x1CE
+//#define CMD8_ARG (0x0UL << 12 | BIT8 | 0xCEUL << 0)
+#define CMD8_ARG (0x0UL << 12 | BIT8 | 0xAAUL << 0)
+
+#define CMD9 (INDX(9) | ENCMDCRC | RSPTYP136)
+#define CMD9_INT_EN (CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD13 (INDX(13) | RSPTYP48)
+#define CMD13_INT_EN (CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+
+//#define CMD16 (INDX(16) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD16 (INDX(16) | ENCMDIDX | RSPTYP48)
+#define CMD16_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD17 (INDX(17) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48 | RD1WT0)
+#define CMD17_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | TRNSCOMP | RDYFORRD | CMDTOUTERR | DATATOUTERR | DATACRCERR | DATAEBITERR | CMDEBITERR)
+
+//#define CMD18 (INDX(18) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48 | MUL1SIN0 | RD1WT0 | ENBLKCNT | ENDMA)
+#define CMD18 (INDX(18) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48 )
+#define CMD18_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | TRNSCOMP | RDYFORRD | CMDTOUTERR | DATATOUTERR | DATACRCERR | DATAEBITERR | CMDEBITERR)
+
+#define CMD23 (INDX(23) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD23_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD24 (INDX(24) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD24_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | TRNSCOMP | RDYFORWT | CMDTOUTERR | DATATOUTERR | DATACRCERR | DATAEBITERR | CMDEBITERR)
+
+//#define CMD25 (INDX(25) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48 | MUL1SIN0 | ENBLKCNT | ENDMA)
+#define CMD25 (INDX(25) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD25_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | TRNSCOMP | RDYFORWT | CMDTOUTERR | DATATOUTERR | DATACRCERR | DATAEBITERR | CMDEBITERR)
+
+//#define CMD55 (INDX(55) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD55 (INDX(55) | ENCMDIDX | RSPTYP48)
+#define CMD55_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define ACMD41 (INDX(41) | RSPTYP48)
+#define ACMD41_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define ACMD6 (INDX(6) | RSPTYP48)
+#define ACMD6_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD62 (INDX(62) | RSPTYP48)
+#define CMD62_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+
+
+/*
+EFI_STATUS
+EFI_SUCCESS 0
+
+EFI_LOAD_ERROR 1
+EFI_INVALID_PARAMETER 2
+EFI_UNSUPPORTED 3
+EFI_BAD_BUFFER_SIZE 4
+EFI_BUFFER_TOO_SMALL 5
+EFI_NOT_READY 6
+EFI_DEVICE_ERROR 7
+EFI_WRITE_PROTECTED 8
+EFI_OUT_OF_RESOURCES 9
+EFI_VOLUME_CORRUPTED 10
+EFI_VOLUME_FULL 11
+EFI_NO_MEDIA 12
+EFI_MEDIA_CHANGED 13
+EFI_NOT_FOUND 14
+EFI_ACCESS_DENIED 15
+EFI_NO_RESPONSE 16
+EFI_NO_MAPPING 17
+EFI_TIMEOUT 18
+EFI_NOT_STARTED 19
+EFI_ALREADY_STARTED 20
+EFI_ABORTED 21
+EFI_ICMO_ERROR 22
+EFI_TFTP_ERROR 23
+EFI_PROTOCOL_ERROR 24
+EFI_INCOMPATIBLE_VERSION 25
+EFI_SECURITY_VIOLATION 26
+EFI_CRC_ERROR 27
+EFI_END_OF_MEDIA 28
+EFI_END_OF_FILE 31
+EFI_INVALID_LANGUAGE 32
+EFI_COMPROMISED_DATA 33
+
+
+*/
+
+#endif
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.c
new file mode 100644
index 000000000..4eab280e6
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.c
@@ -0,0 +1,469 @@
+/** @file
+ Template for Timer Architecture Protocol driver of the ARM flavor
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+
+#include <Protocol/Timer.h>
+#include <Protocol/HardwareInterrupt.h>
+
+#include <Library/ExynosTimerLib.h>
+#include <Platform/ArmPlatform.h>
+
+// The notification function to call on every timer interrupt.
+volatile EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL;
+EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
+
+// The current period of the timer interrupt
+volatile UINT64 mTimerPeriod = 0;
+
+// Cached copy of the Hardware Interrupt protocol instance
+EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
+
+// Cached interrupt vector
+UINTN gVector;
+
+UINT32 mLastTickCount;
+
+/**
+
+ C Interrupt Handler called in the interrupt context when Source interrupt is active.
+
+
+ @param Source Source of the interrupt. Hardware routing off a specific platform defines
+ what source means.
+
+ @param SystemContext Pointer to system register context. Mostly used by debuggers and will
+ update the system context after the return from the interrupt if
+ modified. Don't change these values unless you know what you are doing
+
+**/
+VOID
+EFIAPI
+TimerInterruptHandler (
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ EFI_TPL OriginalTPL;
+ UINT32 Tmp;
+ UINT32 PWMTimerBase;
+
+
+ PWMTimerBase=PcdGet32(PcdPWMTimerBase);
+ //DEBUG ((EFI_D_ERROR, "PWM Timer INT Occur\n"));
+ //
+ // DXE core uses this callback for the EFI timer tick. The DXE core uses locks
+ // that raise to TPL_HIGH and then restore back to current level. Thus we need
+ // to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
+ //
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ // clear the periodic interrupt
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TINT_CSTAT_OFFSET);
+ MmioWrite32 ((PWMTimerBase + PWM_TINT_CSTAT_OFFSET), Tmp);
+
+ // signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers
+ gInterrupt->EndOfInterrupt (gInterrupt, Source);
+
+ if (mTimerNotifyFunction) {
+ mTimerNotifyFunction (mTimerPeriod);
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+}
+
+/**
+ This function registers the handler NotifyFunction so it is called every time
+ the timer interrupt fires. It also passes the amount of time since the last
+ handler call to the NotifyFunction. If NotifyFunction is NULL, then the
+ handler is unregistered. If the handler is registered, then EFI_SUCCESS is
+ returned. If the CPU does not support registering a timer interrupt handler,
+ then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
+ when a handler is already registered, then EFI_ALREADY_STARTED is returned.
+ If an attempt is made to unregister a handler when a handler is not registered,
+ then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
+ register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
+ is returned.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param NotifyFunction The function to call when a timer interrupt fires. This
+ function executes at TPL_HIGH_LEVEL. The DXE Core will
+ register a handler for the timer interrupt, so it can know
+ how much time has passed. This information is used to
+ signal timer based events. NULL will unregister the handler.
+ @retval EFI_SUCCESS The timer handler was registered.
+ @retval EFI_UNSUPPORTED The platform does not support timer interrupts.
+ @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
+ registered.
+ @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
+ previously registered.
+ @retval EFI_DEVICE_ERROR The timer handler could not be registered.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverRegisterHandler (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN EFI_TIMER_NOTIFY NotifyFunction
+ )
+{
+ if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ DEBUG ((EFI_D_ERROR, "++TimerDriverRegisterHandler\n"));
+ mTimerNotifyFunction = NotifyFunction;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Make sure all ArrmVe Timers are disabled
+**/
+VOID
+EFIAPI
+ExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINT32 PWMTimerBase;
+
+ PWMTimerBase=PcdGet32(PcdPWMTimerBase);
+ // All PWM timer is off
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), 0);
+}
+
+/**
+
+ This function adjusts the period of timer interrupts to the value specified
+ by TimerPeriod. If the timer period is updated, then the selected timer
+ period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
+ If an error occurs while attempting to update the timer period, then the
+ timer hardware will be put back in its state prior to this call, and
+ EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
+ is disabled. This is not the same as disabling the CPU's interrupts.
+ Instead, it must either turn off the timer hardware, or it must adjust the
+ interrupt controller so that a CPU interrupt is not generated when the timer
+ interrupt fires.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
+ the timer hardware is not programmable, then EFI_UNSUPPORTED is
+ returned. If the timer is programmable, then the timer period
+ will be rounded up to the nearest timer period that is supported
+ by the timer hardware. If TimerPeriod is set to 0, then the
+ timer interrupts will be disabled.
+
+
+ @retval EFI_SUCCESS The timer period was changed.
+ @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
+ @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverSetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ IN UINT64 TimerPeriod
+ )
+{
+ EFI_STATUS Status;
+ UINT64 TimerTicks;
+ UINT32 Tmp;
+ UINT32 PWMTimerBase;
+
+ PWMTimerBase=PcdGet32(PcdPWMTimerBase);
+ // Stop PWM timer 0
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCON_OFFSET);
+ Tmp &= ~(0x1F << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET) ,Tmp);
+
+ if (TimerPeriod == 0) {
+ // leave timer disabled from above, and...
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TINT_CSTAT_OFFSET);
+ Tmp &= ~(1 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TINT_CSTAT_OFFSET), Tmp);
+ // disable timer 0/1 interrupt for a TimerPeriod of 0
+ Status = gInterrupt->DisableInterruptSource (gInterrupt, gVector);
+ } else {
+ // Convert TimerPeriod into 1MHz clock counts (us units = 100ns units / 10)
+ TimerTicks = DivU64x32 (TimerPeriod, 10);
+ // if it's larger than 32-bits, pin to highest value
+ if (TimerTicks > 0xffffffff) {
+ TimerTicks = 0xffffffff;
+ }
+
+ // PWM Timer 0 used by Period counter with Auto re-load mode
+ MmioWrite32 ((PWMTimerBase + PWM_TCNTB0_OFFSET), TimerTicks);
+ // Set and Clear PWM Manually update for Timer 0
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCON_OFFSET);
+ Tmp |= (0x2 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ Tmp &= ~(0x2 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ // Set Auto re-load and start Timer
+ Tmp |= (0x9 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+ // enable PWM Timer 0 interrupts
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TINT_CSTAT_OFFSET);
+ Tmp |= (1 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TINT_CSTAT_OFFSET), Tmp);
+
+ Status = gInterrupt->EnableInterruptSource (gInterrupt, gVector);
+ }
+
+ // Save the new timer period
+ mTimerPeriod = TimerPeriod;
+ return Status;
+}
+
+/**
+ This function retrieves the period of timer interrupts in 100 ns units,
+ returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
+ is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
+ returned, then the timer is currently disabled.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+ @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
+ 0 is returned, then the timer is currently disabled.
+
+
+ @retval EFI_SUCCESS The timer period was returned in TimerPeriod.
+ @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGetTimerPeriod (
+ IN EFI_TIMER_ARCH_PROTOCOL *This,
+ OUT UINT64 *TimerPeriod
+ )
+{
+ if (TimerPeriod == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerPeriod = mTimerPeriod;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function generates a soft timer interrupt. If the platform does not support soft
+ timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
+ If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
+ service, then a soft timer interrupt will be generated. If the timer interrupt is
+ enabled when this service is called, then the registered handler will be invoked. The
+ registered handler should not be able to distinguish a hardware-generated timer
+ interrupt from a software-generated timer interrupt.
+
+ @param This The EFI_TIMER_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The soft timer interrupt was generated.
+ @retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts.
+
+**/
+EFI_STATUS
+EFIAPI
+TimerDriverGenerateSoftInterrupt (
+ IN EFI_TIMER_ARCH_PROTOCOL *This
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Interface structure for the Timer Architectural Protocol.
+
+ @par Protocol Description:
+ This protocol provides the services to initialize a periodic timer
+ interrupt, and to register a handler that is called each time the timer
+ interrupt fires. It may also provide a service to adjust the rate of the
+ periodic timer interrupt. When a timer interrupt occurs, the handler is
+ passed the amount of time that has passed since the previous timer
+ interrupt.
+
+ @param RegisterHandler
+ Registers a handler that will be called each time the
+ timer interrupt fires. TimerPeriod defines the minimum
+ time between timer interrupts, so TimerPeriod will also
+ be the minimum time between calls to the registered
+ handler.
+
+ @param SetTimerPeriod
+ Sets the period of the timer interrupt in 100 nS units.
+ This function is optional, and may return EFI_UNSUPPORTED.
+ If this function is supported, then the timer period will
+ be rounded up to the nearest supported timer period.
+
+
+ @param GetTimerPeriod
+ Retrieves the period of the timer interrupt in 100 nS units.
+
+ @param GenerateSoftInterrupt
+ Generates a soft timer interrupt that simulates the firing of
+ the timer interrupt. This service can be used to invoke the registered handler if the timer interrupt has been masked for
+ a period of time.
+
+**/
+EFI_TIMER_ARCH_PROTOCOL gTimer = {
+ TimerDriverRegisterHandler,
+ TimerDriverSetTimerPeriod,
+ TimerDriverGetTimerPeriod,
+ TimerDriverGenerateSoftInterrupt
+};
+
+
+/**
+ Initialize the state information for the Timer Architectural Protocol and
+ the Timer Debug support protocol that allows the debugger to break into a
+ running program.
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+TimerInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE Handle = NULL;
+ EFI_STATUS Status;
+
+ UINT32 Tmp;
+ UINT32 PWMTimerBase;
+
+ PWMTimerBase=PcdGet32(PcdPWMTimerBase);
+ // Find the interrupt controller protocol. ASSERT if not found.
+ Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
+ ASSERT_EFI_ERROR (Status);
+
+ // Timer Source : SCLK_MPLL(800Mhz)
+ Tmp = MmioRead32(0x10020250);
+ Tmp &= ~(0xF << 24);
+ Tmp |= (0x6 << 24);
+ MmioWrite32(0x10020250, Tmp);
+ // Timer 0,1,2 prescale:0x02(/(0x02+1)) => 266666666hz (at least 0x01+1)
+ Tmp = MmioRead32(PWMTimerBase + PWM_TCFG0_OFFSET);
+ Tmp &= ~((0xFF << 8) + (0xFF << 0));
+ Tmp |= (0x02 << 8) + (0x02 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCFG0_OFFSET), Tmp);
+ // Timer 0,1,2 divider:0x2(/4) => 66666666hz
+ MmioWrite32 ((PWMTimerBase + PWM_TCFG1_OFFSET), (0x2 << 2) + (0x2 << 1) + (0x2 << 0));
+/*
+ // PWM Input source clock is 100Mhz and Configure 1Mhz for PWM Timer
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCFG0_OFFSET);
+ Tmp &= ~(0xFF << 0);
+ Tmp |= (0x63 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCFG0_OFFSET), Tmp);
+ MmioWrite32 ((PWMTimerBase + PWM_TCFG1_OFFSET), 0x0);
+*/
+ //Timer 1 INT disable
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TINT_CSTAT_OFFSET);
+ Tmp &= ~(1 << 1);
+ MmioWrite32 ((PWMTimerBase + PWM_TINT_CSTAT_OFFSET), Tmp);
+
+ // configure timer 1 Stop
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCON_OFFSET);
+ Tmp &= ~(0xF << 8);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+ // PWM Timer 1 used by Free running counter with Auto re-load mode
+ MmioWrite32 ((PWMTimerBase + PWM_TCNTB1_OFFSET), 0xFFFFFFFF);
+ // Set and Clear PWM Manually update for Timer 1
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCON_OFFSET);
+ Tmp |= (0x2 << 8);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ Tmp &= ~(0x2 << 8);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ // Set Auto re-load and start Timer
+ Tmp |= (0x9 << 8);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+ // Install interrupt handler
+ gVector = PWM_TIMER0_INTERRUPT_NUM;
+ Status = gInterrupt->RegisterInterruptSource (gInterrupt, gVector, TimerInterruptHandler);
+ ASSERT_EFI_ERROR (Status);
+
+ // Disable the timer
+ Status = TimerDriverSetTimerPeriod (&gTimer, 0);
+ ASSERT_EFI_ERROR (Status);
+
+ // PWM Timer 0 make to stop
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCON_OFFSET);
+ Tmp &= ~(0x1F << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+ // PWM Timer 0 INT disable
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TINT_CSTAT_OFFSET);
+ Tmp &= ~(1 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TINT_CSTAT_OFFSET), Tmp);
+
+ // PWM Timer 0 used by Period counter with Auto re-load mode
+ MmioWrite32 ((PWMTimerBase + PWM_TCNTB0_OFFSET), FixedPcdGet32(PcdTimerPeriod));
+ Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod));
+ ASSERT_EFI_ERROR (Status);
+
+ // Set and Clear PWM Manually update for Timer 0
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCON_OFFSET);
+ Tmp |= (0x2 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ Tmp &= ~(0x2 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ // Set Auto re-load and start Timer
+ Tmp |= (0x9 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+ //PWM Timer0 INT enable
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TINT_CSTAT_OFFSET);
+ Tmp |= (1 << 0);
+ MmioWrite32 ((PWMTimerBase + PWM_TINT_CSTAT_OFFSET), Tmp);
+
+ // Install the Timer Architectural Protocol onto a new handle
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gEfiTimerArchProtocolGuid, &gTimer,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ // Register for an ExitBootServicesEvent
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.inf
new file mode 100644
index 000000000..019d84477
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.inf
@@ -0,0 +1,54 @@
+#/** @file
+#
+# Component discription file for Timer module
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = TimerDxe
+ FILE_GUID = 494ffd22-3228-4b7e-ad40-7e780fa88301
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = TimerInitialize
+
+[Sources.common]
+ TimerDxe.c
+
+[Packages]
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ TimerLib
+
+[Guids]
+
+[Protocols]
+ gEfiTimerArchProtocolGuid
+ gHardwareInterruptProtocolGuid
+
+
+[Pcd.common]
+ gEmbeddedTokenSpaceGuid.PcdTimerPeriod
+ gExynosPkgTokenSpaceGuid.PcdPWMTimerBase
+[Depex]
+ gHardwareInterruptProtocolGuid
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c
new file mode 100755
index 000000000..87f937924
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.c
@@ -0,0 +1,1378 @@
+/** @file
+ MMC/SD Card driver for Secure Digital Host Controller
+
+ This driver always produces a BlockIo protocol but it starts off with no Media
+ present. A TimerCallBack detects when media is inserted or removed and after
+ a media change event a call to BlockIo ReadBlocks/WriteBlocks will cause the
+ media to be detected (or removed) and the BlockIo Media structure will get
+ updated. No MMC/SD Card harward registers are updated until the first BlockIo
+ ReadBlocks/WriteBlocks after media has been insterted (booting with a card
+ plugged in counts as an insertion event).
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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/TimerLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/ExynosGpio.h>
+#include <Platform/ArmPlatform.h>
+#include <Platform/Exynos5250.h>
+#include <Platform/Arndale5250.h>
+
+#include "eMMCDxe.h"
+
+
+
+#define DateInformation "20120723_007"
+
+
+MSHC_OPERATION_MODE MSHC_operation_mode=MSHC_FIFO;
+//MSHC_OPERATION_MODE MSHC_operation_mode=MSHC_IDMA;
+
+
+//#undef EFI_D_INFO
+//#define EFI_D_INFO 1
+
+
+
+CARD_INFO gCardInfo;
+BOOLEAN gMediaChange = TRUE;
+BOOLEAN gCardInit = FALSE;
+
+
+EFI_BLOCK_IO_MEDIA gSDMMCMedia = {
+ SIGNATURE_32('e','m','m','c'), // MediaId
+ FALSE, // RemovableMedia
+ TRUE, // MediaPresent
+ FALSE, // LogicalPartition
+ FALSE, // ReadOnly
+ FALSE, // WriteCaching
+ 512, // BlockSize
+ 4, // IoAlign
+ 0, // Pad
+ 0 // LastBlock
+};
+
+typedef struct {
+ VENDOR_DEVICE_PATH Mmc;
+ EFI_DEVICE_PATH End;
+} MSHC_DEVICE_PATH;
+
+MSHC_DEVICE_PATH gMSHCDevicePath = {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ (UINT8)(sizeof(VENDOR_DEVICE_PATH)),
+ (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
+ 0xb615f1f5, 0x5088, 0x43cd, 0x80, 0x9c, 0xa1, 0x6e, 0x52, 0x48, 0x7d, 0x00
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0
+ }
+};
+
+
+
+//
+// Internal Functions
+//
+
+
+
+
+VOID
+ParseCardCIDData (
+ UINT32 Response0,
+ UINT32 Response1,
+ UINT32 Response2,
+ UINT32 Response3
+ )
+{
+ gCardInfo.CIDData.MDT = ((Response0 >> 8) & 0xFFF);
+ gCardInfo.CIDData.PSN = (((Response0 >> 24) & 0xFF) | ((Response1 & 0xFFFFFF) << 8));
+ gCardInfo.CIDData.PRV = ((Response1 >> 24) & 0xFF);
+ gCardInfo.CIDData.PNM[4] = ((Response2) & 0xFF);
+ gCardInfo.CIDData.PNM[3] = ((Response2 >> 8) & 0xFF);
+ gCardInfo.CIDData.PNM[2] = ((Response2 >> 16) & 0xFF);
+ gCardInfo.CIDData.PNM[1] = ((Response2 >> 24) & 0xFF);
+ gCardInfo.CIDData.PNM[0] = ((Response3) & 0xFF);
+ gCardInfo.CIDData.OID = ((Response3 >> 8) & 0xFFFF);
+ gCardInfo.CIDData.MID = ((Response3 >> 24) & 0xFF);
+}
+
+
+EFI_STATUS
+MSHC_SendCmd (
+ UINTN Cmd,
+ UINTN CmdInterruptEnableVal,
+ UINTN CmdArgument
+ )
+{
+ UINTN MmcStatus = 0;
+ volatile UINTN RetryCount = 0;
+ int cmd_flags = 0;
+ int timeout=0;
+ UINT32 SdMmcBaseAddr;
+ //UINT32 MSHCRintStatus=0;
+
+ DEBUG ((EFI_D_INFO, "CMD = %d\n", (Cmd&0x3F)));
+
+ timeout = MAX_RETRY_COUNT;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ //1. Check if Data busy or not
+ while(MmioRead32(SdMmcBaseAddr + MSHCI_STATUS) & (DATA_BUSY))
+ {
+ if (timeout == 0)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd timeout : CMD = %d\n", Cmd));
+ return EFI_DEVICE_ERROR;
+ }
+ timeout--;
+ MicroSecondDelay(1);
+ }
+
+ // 2. Check if Raw interrupt is command done
+ /*MSHCRintStatus = MmioRead32(SdMmcBaseAddr + MSHCI_RINTSTS);
+ if ((MSHCRintStatus & (INTMSK_CDONE|INTMSK_ACD)) == 0)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd interrupt error : INT = %x\n", MmioRead32(SdMmcBaseAddr + MSHCI_RINTSTS)));
+ } */
+
+ // 3. Clear Raw interrupt
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_RINTSTS), INTMSK_ALL);
+
+ // 4. prepare data
+ //mshci_reset_fifo();
+
+ //5. Set command argument register
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMDARG), CmdArgument);
+
+ // 6. transfer data
+
+ //Enable interrupt enable events to occur
+ // EVT1 do not need interrupt mask, use Raw interrupt
+ //MmioWrite32 ((SdMmcBaseAddr + MSHCI_INTMSK), CmdInterruptEnableVal);
+
+ // 7. trasfer data
+
+ //8. Send a command
+ cmd_flags = (Cmd & 0x3F);
+ if(Cmd & (RSPTYP48 | RSPTYP48B | RSPTYP136))
+ {
+ cmd_flags |= CMD_RESP_EXP_BIT;
+ if(Cmd & RSPTYP136)
+ cmd_flags |= CMD_RESP_LENGTH_BIT;
+ }
+
+ if((Cmd==CMD17)|(Cmd==CMD18)|(Cmd==CMD8))
+ {
+ cmd_flags |= CMD_DATA_EXP_BIT;
+ //DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Read\n"));
+ }
+
+ if((Cmd==CMD24)|(Cmd==CMD25))
+ {
+ cmd_flags |= CMD_DATA_EXP_BIT | CMD_RW_BIT;
+ //DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Write\n"));
+
+ }
+
+ if (Cmd & ENCMDCRC)
+ {
+ cmd_flags |= CMD_CHECK_CRC_BIT;
+ }
+ cmd_flags |= (CMD_STRT_BIT | CMD_USE_HOLD_REG | CMD_WAIT_PRV_DAT_BIT|CMD_SENT_AUTO_STOP_BIT);
+ //cmd_flags |= (CMD_STRT_BIT | CMD_USE_HOLD_REG | CMD_WAIT_PRV_DAT_BIT);
+ DEBUG ((EFI_D_INFO, "CMD flag = 0x%x\n", cmd_flags));
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), cmd_flags);
+ MicroSecondDelay(1);
+
+ //9. Check for the Raw interrupt
+ //wait for command complete by busy waiting.
+ for (RetryCount; RetryCount<MAX_RETRY_COUNT; RetryCount++)
+ {
+ MmcStatus = MmioRead32(SdMmcBaseAddr + MSHCI_RINTSTS);
+ if (MmcStatus & INTMSK_CDONE)
+ {
+ break;
+ }
+ }
+
+ if (RetryCount == MAX_RETRY_COUNT)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd timeout CMD:%d RINT:0x%x\n",(Cmd&0x3F) ,MmcStatus));
+ return EFI_TIMEOUT;
+ }
+
+ if(MmcStatus & INTMSK_RTO)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Response timeout CMD:%d RINT:0x%x\n", (Cmd & 0x3F),MmcStatus));
+ return EFI_TIMEOUT;
+
+ }
+ else if (MmcStatus & INTMSK_RE)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Response Error RINT:0x%x\n", MmcStatus));
+ return EFI_TIMEOUT;
+ }
+ else if(MmcStatus & INTMSK_RCRC)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Response CRC Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_DCRC)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd Data CRC Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_HLE)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd HLE Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_SBE)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd SBE Err RINT:0x%x\n", MmcStatus));
+ else if(MmcStatus & INTMSK_EBE)
+ DEBUG ((EFI_D_ERROR, "MSHC::MSHC_SendCmd EBE Err RINT:0x%x\n", MmcStatus));
+
+ return EFI_SUCCESS;
+}
+
+/**
+Super block size : 4MB (16GB density)
+Argument (Boot Size) =(Number of Super Block for boot partition) / 2
+
+**/
+EFI_STATUS MSHC_BOOT_Partition(UINT32 bootsize, UINT32 rpmbsize)
+{
+ UINTN CmdArgument;
+ EFI_STATUS Status = RETURN_SUCCESS;
+ UINT32 BootSize, RPMBSize;
+
+ /* Only use this command for raw eMMC moviNAND */
+ /* Enter backdoor mode */
+ CmdArgument = 0xefac62ec;
+ Status = MSHC_SendCmd (CMD62, CMD62_INT_EN, CmdArgument);
+
+ /* Boot partition changing mode */
+ CmdArgument = 0xcbaea7;
+ Status = MSHC_SendCmd (CMD62, CMD62_INT_EN, CmdArgument);
+
+ //BootSize = ((bootsize*1024)/128);
+ BootSize = (bootsize*2);
+
+ /* Arg: boot partition size */
+ CmdArgument = BootSize;
+ Status = MSHC_SendCmd (CMD62, CMD62_INT_EN, CmdArgument);
+
+ //RPMBSize = ((rpmbsize*1024)/128);
+ RPMBSize = (rpmbsize*2);
+
+ /* Arg: RPMB partition size */
+ CmdArgument = RPMBSize;
+ Status = MSHC_SendCmd (CMD62, CMD62_INT_EN, CmdArgument);
+
+ return Status;
+
+}
+
+EFI_STATUS MSHC_EMMC_Boot_Open()
+{
+ UINTN CmdArgument;
+ EFI_STATUS Status = RETURN_SUCCESS;
+
+ DEBUG ((EFI_D_INFO, "emmc open\n" ));
+ /* Boot ack enable, boot partition enable , boot partition access */
+ CmdArgument = ((3<<24)|(179<<16)|(((1<<6)|(1<<3)|(1<<0))<<8));
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, CmdArgument);
+ if (!EFI_ERROR(Status))
+ {
+ /* 4bit transfer mode at booting time. */
+ CmdArgument = ((3<<24)|(177<<16)|((1<<0)<<8));
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "emmc open fail 2nd CMD6\n" ));
+ }
+ }
+ else
+ {
+ DEBUG ((EFI_D_ERROR, "emmc open fail first CMD6\n" ));
+ }
+
+ return Status;
+}
+
+EFI_STATUS MSHC_EMMC_Boot_Close()
+{
+ UINTN CmdArgument;
+ EFI_STATUS Status = RETURN_SUCCESS;
+
+ DEBUG ((EFI_D_INFO, "emmc close\n" ));
+ CmdArgument = ((3<<24)|(179<<16)|(((1<<6)|(1<<3)|(0<<0))<<8));
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "emmc close fail \n" ));
+ }
+ return Status;
+}
+
+
+void PrintCardInfo()
+{
+ DEBUG ((EFI_D_INFO, "MSHC::READ_BL_LEN %d\n", gCardInfo.CSDData.READ_BL_LEN));
+ DEBUG ((EFI_D_INFO, "MSHC::CSize %d\n", gCardInfo.CSDData.C_SIZELow2 | (gCardInfo.CSDData.C_SIZEHigh10 << 2)));
+ DEBUG ((EFI_D_INFO, "MSHC::MULTI %d\n", gCardInfo.CSDData.C_SIZE_MULT));
+
+}
+
+
+#define EXT_CSD_SIZE 128
+UINT32 Ext_csd[EXT_CSD_SIZE];
+VOID GetEXTCSD()
+{
+ gCardInfo.NumBlocks = 0;
+ gCardInfo.TotalNumBlocks = 30801920;
+
+ UINTN cmdarg = 0;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_HS_TIMING << 16) |
+ (0 << 8);
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, cmdarg);
+
+ cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_BUS_WIDTH << 16) |
+ (EXT_CSD_BUS_WIDTH_1 << 8);
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, cmdarg);
+
+ cmdarg = 0;
+ Status = MSHC_SendCmd (CMD8, CMD8_INT_EN, cmdarg);
+
+ gCardInfo.BlockSize = BLEN_512BYTES;
+
+ if (!EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::EXT CSD \n"));
+ //PrepareTransfer(&Ext_csd[0], 1, READ);
+ //MSHC_ReadDMA(&Ext_csd[0], 1);
+ MSHC_ReadFIFO(EXT_CSD_SIZE, &Ext_csd[0]);
+ gCardInfo.NumBlocks = Ext_csd[EXT_CSD_SEC_CNT/4];
+ gCardInfo.Extcsd.boot_size_multi = Ext_csd[BOOT_SIZE_MULTI/4];
+ gCardInfo.Extcsd.boot_size_multi = (gCardInfo.Extcsd.boot_size_multi>>16)&0xff;
+ //MicroSecondDelay(5000);
+
+ DEBUG ((EFI_D_INFO, "MSHC::num blocks %d\n", gCardInfo.NumBlocks));
+ DEBUG ((1, "MSHC::eMMC Size:%dMB\n", (gCardInfo.NumBlocks/2048)));
+ DEBUG ((1, "MSHC::Boot partition Size:%dMB\n", ((gCardInfo.TotalNumBlocks-gCardInfo.NumBlocks)/2048)));
+ DEBUG ((EFI_D_INFO, "MSHC::Ext CSD boot block %d\n", (gCardInfo.Extcsd.boot_size_multi)));
+
+ }
+ else
+ {
+ gCardInfo.NumBlocks = 0x1D4C000;
+ DEBUG ((EFI_D_ERROR, "MSHC:: default block number : 0x1D4C000"));
+ }
+
+}
+
+
+EFI_STATUS
+PerformCardIdenfication (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN CmdArgument = 0;
+ //UINTN Response = 0;
+ //UINTN RetryCount = 0;
+ UINTN TempRes0,TempRes1,TempRes2,TempRes3;
+ //BOOLEAN SDCmd8Supported = FALSE;
+ UINT32 SdMmcBaseAddr;
+ int timeout = MAX_RETRY_COUNT;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+ gCardInfo.CardType = MMC_CARD;
+
+ //1. Send CMD0 command. go to IDLE
+ Status = MSHC_SendCmd (CMD0, CMD0_INT_EN, CmdArgument);
+
+ // 2. Send CMD1 while OCR is not busy and get OCR register
+ do {
+ CmdArgument = OCR_HCS | MMC_VDD_32_33 | MMC_VDD_33_34;
+ Status = MSHC_SendCmd (CMD1, CMD1_INT_EN, CmdArgument);
+
+ if (EFI_ERROR(Status))
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::CMD1 fails.\n"));
+ }
+
+ MicroSecondDelay(100);
+ } while (!(MmioRead32 (SdMmcBaseAddr + MSHCI_RESP0)& OCR_BUSY) && timeout--);
+
+ if (timeout <= 0)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::CMD1 OCR busy timeout.\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ DEBUG ((EFI_D_INFO, "MSHC::CMD1 OCR 0x%x\n", MmioRead32(SdMmcBaseAddr + MSHCI_RESP0)));
+
+ ((UINT32 *) &(gCardInfo.OCRData))[0] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+
+ //3. send CMD2 to get CID register
+ CmdArgument = 0;
+ Status = MSHC_SendCmd (CMD2, CMD2_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD2 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD2 response: %x %x %x %x\n", MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0)), \
+ MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP1)), \
+ MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP2)), \
+ MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP3))));
+
+ TempRes0 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+ TempRes1 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP1));
+ TempRes2 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP2));
+ TempRes3 = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP3));
+
+ //Parse CID register data.
+ ParseCardCIDData(TempRes0 << 8, (TempRes1 << 8) | (TempRes0 >> 24),
+ (TempRes2 << 8) | (TempRes1 >> 24), (TempRes3 << 8) | (TempRes2 >> 24));
+
+ //4. send CMD3 to get RCA register
+ CmdArgument = 0;
+ Status = MSHC_SendCmd (CMD3, CMD3_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD3 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ //Set RCA for the detected card. RCA is CMD3 response.
+ DEBUG ((EFI_D_INFO, "MSHC::CMD3 RCA 0x%x\n", MmioRead32(SdMmcBaseAddr + MSHCI_RESP0)));
+ gCardInfo.RCA = (MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0)) >> 16);
+ DEBUG ((EFI_D_INFO, "CMD3 response: RCA %x\n", gCardInfo.RCA));
+
+ gBS->Stall(1000); //Need Debug by wprkfgur
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+GetCardSpecificData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN CmdArgument;
+ UINTN TempRes[4],i;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ //Send CMD9 to retrieve CSD.
+ CmdArgument = gCardInfo.RCA << 16;
+ Status = MSHC_SendCmd (CMD9, CMD9_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD9 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ TempRes[0] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP0));
+ TempRes[1] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP1));
+ TempRes[2] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP2));
+ TempRes[3] = MmioRead32 ((SdMmcBaseAddr + MSHCI_RESP3));
+
+ //Populate 128-bit CSD register data.
+ for (i = 0 ; i < 4; i++) {
+ ((UINT32 *)&(gCardInfo.CSDData))[i] = TempRes[i];
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD9 response: %x %x %x %x\n", ((UINT32 *)&(gCardInfo.CSDData))[0], ((UINT32 *)&(gCardInfo.CSDData))[1], ((UINT32 *)&(gCardInfo.CSDData))[2], ((UINT32 *)&(gCardInfo.CSDData))[3]));
+ return Status;
+}
+
+EFI_STATUS
+PerformCardConfiguration (
+ VOID
+ )
+{
+ UINTN CmdArgument = 0;
+ EFI_STATUS Status;
+ UINT32 SdMmcBaseAddr;
+ //UINTN FifoCount = 0;
+ //UINTN Count=0;
+ UINT32 OMval;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+ OMval = MmioRead32(0x10040000);
+ DEBUG ((EFI_D_INFO, "MSHC::OM read 0x%x \n", OMval));
+
+ //Send CMD7
+ CmdArgument = gCardInfo.RCA << 16;
+ Status = MSHC_SendCmd (CMD7, CMD7_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD7 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ //Send CMD16 to set the block length
+ //CmdArgument = gCardInfo.BlockSize;
+ CmdArgument = BLEN_512BYTES;
+ Status = MSHC_SendCmd (CMD16, CMD16_INT_EN, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD16 fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ if(OMval!=OM_EMMC)
+ {
+ GetEXTCSD();
+ if(gCardInfo.Extcsd.boot_size_multi!= MSHC_BOOT_SIZE_MULTI)
+ {
+ MSHC_BOOT_Partition(MSHC_BOOT_SIZE, MSHC_RPMB_SIZE);
+ DEBUG ((EFI_D_INFO, "MSHC::Doing Boot partition \n"));
+ }
+ else
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::Alread boot partition \n", Status));
+ }
+ }
+ else
+ {
+ DEBUG ((1, "MSHC::eMMC booting \n"));
+ gCardInfo.TotalNumBlocks = 30801920;
+ gCardInfo.NumBlocks = 30588928;
+ }
+
+ // set device into 4-bit data bus mode
+ //Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, 0x2);
+ // set device into 8-bit data bus mode
+ CmdArgument = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (EXT_CSD_BUS_WIDTH <<16) |
+ (EXT_CSD_BUS_WIDTH_8_DDR <<8);
+ Status = MSHC_SendCmd (ACMD6, ACMD6_INT_EN, CmdArgument);
+ if (!EFI_ERROR (Status)) {
+ // Set host controler into 8-bit mode
+ MmioOr32 ((SdMmcBaseAddr + MSHCI_CTYPE), CARD_WIDTH8);
+ //MmioOr32 ((SdMmcBaseAddr + MSHCI_CTYPE), CARD_WIDTH14);
+ DEBUG ((EFI_D_INFO, "8-bit mode\n"));
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReadBlockData (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ OUT VOID *Buffer,
+ IN UINTN BlockCount
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ UINTN DataSize = This->Media->BlockSize/4;
+
+ DEBUG ((EFI_D_INFO, "MSHC::ReadBlockData start \n"));
+
+ if(MSHC_operation_mode == MSHC_FIFO)
+ {
+ Status = MSHC_ReadFIFO(DataSize, Buffer);
+ }
+
+ else if(MSHC_operation_mode == MSHC_IDMA)
+ {
+ Status = MSHC_ReadDMA(Buffer, BlockCount);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+WriteBlockData (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ OUT VOID *Buffer,
+ IN UINTN BlockCount
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ UINTN DataSize = This->Media->BlockSize/4;
+
+ if(MSHC_operation_mode == MSHC_FIFO)
+ {
+ Status = MSHC_WriteFIFO(DataSize, Buffer);
+ }
+ else if(MSHC_operation_mode == MSHC_IDMA)
+ {
+ Status = MSHC_WriteDMA(Buffer, BlockCount);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EraseBlockData (
+ IN UINT32 Partition,
+ IN UINTN StartBlock,
+ IN UINTN NumBlock
+ )
+{
+ UINTN cmdarg = 0;
+ EFI_STATUS status = EFI_SUCCESS;
+
+ if(Partition!=MSHC_BOOT_PARTITION)
+ {
+ DEBUG ((EFI_D_ERROR, "EraseBlockData failed \n"));
+ status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ /* MMC High Capacity erase minimum size is 512KB */
+ if (NumBlock < 1024) {
+ if (NumBlock < 512)
+ NumBlock = 1;
+ else
+ NumBlock = 2;
+ } else {
+ if (0 == (NumBlock%1024)) {
+ NumBlock = (NumBlock / 1024);
+ } else {
+ NumBlock = (NumBlock / 1024) + 1;
+ }
+ }
+ DEBUG ((EFI_D_INFO, "EraseBlockData start:%d, Numblock:%d\n", StartBlock, NumBlock));
+
+ cmdarg = StartBlock;
+ status = MSHC_SendCmd (CMD35, 0, cmdarg);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((EFI_D_ERROR, "EraseBlockData CMD35 failed \n"));
+ status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ cmdarg = StartBlock + NumBlock;
+ status = MSHC_SendCmd (CMD36, 0, cmdarg);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((EFI_D_ERROR, "EraseBlockData CMD36 failed \n"));
+ status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ cmdarg = 0;
+ status = MSHC_SendCmd (CMD38, 0, cmdarg);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((EFI_D_ERROR, "EraseBlockData CMD38 failed \n"));
+ status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+
+ return status;
+}
+
+
+EFI_STATUS
+TransferBlock (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Lba,
+ IN OUT VOID *Buffer,
+ IN UINTN BlockCount,
+ IN OPERATION_TYPE OperationType
+ )
+{
+ EFI_STATUS Status;
+ UINTN Cmd = 0;
+ UINTN CmdInterruptEnable = 0;
+ UINTN CmdArgument = 0;
+
+ // 1. FIFO reset
+ // MSHC_SendCmd do the fifo reset
+
+ // 2. prepare transfer
+
+ DEBUG ((EFI_D_INFO, "SDHC::TransferBlock : Lba = %d, Buffer = 0x%x, Type = %d\n", Lba, Buffer, OperationType));
+ //Populate the command information based on the operation type.
+ if (OperationType == READ)
+ {
+ if(BlockCount>1)
+ {
+ Cmd = CMD18; //multi block read
+ CmdInterruptEnable = CMD18_INT_EN;
+ }
+ else
+ {
+ Cmd = CMD17; //Single block read
+ CmdInterruptEnable = CMD17_INT_EN;
+ }
+
+ }
+ else if (OperationType == WRITE)
+ {
+ if(BlockCount>1)
+ {
+ Cmd = CMD25; //multi block write
+ CmdInterruptEnable = CMD25_INT_EN;
+ }
+ else
+ {
+ Cmd = CMD24; //Single block write
+ CmdInterruptEnable = CMD24_INT_EN;
+ }
+ }
+ PrepareTransfer(Buffer, BlockCount, OperationType);
+
+ //Set command argument based on the card access mode (Byte mode or Block mode)
+ if (gCardInfo.OCRData.AccessMode & BIT1) {
+ CmdArgument = Lba;
+ } else {
+ CmdArgument = Lba * This->Media->BlockSize;
+ }
+
+ //Send Command.
+ Status = MSHC_SendCmd (Cmd, CmdInterruptEnable, CmdArgument);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "CMD%d fails. Status: %x\n", (Cmd&0x3F), Status));
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "CMD%d succeed! \n", (Cmd&0x3F)));
+
+ //Read or Write data.
+ if (OperationType == READ) {
+ Status = ReadBlockData (This, Buffer, BlockCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "ReadBlockData fails.\n"));
+ return Status;
+ }
+ } else if (OperationType == WRITE) {
+ Status = WriteBlockData (This, Buffer, BlockCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "WriteBlockData fails.\n"));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+CardPresent (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+EFI_STATUS
+DetectCard (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ //UINT32 SdMmcBaseAddr;
+
+ //DEBUG ((EFI_D_INFO, "===================================\n"));
+ DEBUG ((EFI_D_INFO, "===MSHC: Version %a ===\n", DateInformation));
+ //DEBUG ((EFI_D_INFO, "===================================\n"));
+
+ //SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ if (!CardPresent ()) {
+ return EFI_NO_MEDIA;
+ }
+
+ //Initialize MMC host controller clocks.
+ Status = InitializeMSHC ();
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "Initialize MMC host controller fails. Status: %x\n", Status));
+ return Status;
+ }
+
+ // EVT1 InitializeSDHC do the SW Reset
+ //Soft reset for all.
+ //MmioWrite32((SdMmcBaseAddr + SDHC_SWRST_OFFSET), SRA);
+ //gBS->Stall(1000);
+ //while ((MmioRead32 ((SdMmcBaseAddr + SDHC_SWRST_OFFSET)) & SRA) != 0x0);
+
+ //Set the clock frequency to 400KHz.
+ UpdateMSHCClkFrequency (MSHC_CLK_400);
+
+ //Card idenfication
+ Status = PerformCardIdenfication ();
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "No MMC/SD card detected.\n"));
+ return Status;
+ }
+
+ //Get CSD (Card specific data) for the detected card.
+ Status = GetCardSpecificData();
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //Configure the card in data transfer mode.
+ Status = PerformCardConfiguration();
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //Patch the Media structure.
+ gSDMMCMedia.LastBlock = (gCardInfo.NumBlocks - 1);
+ //gSDMMCMedia.BlockSize = gCardInfo.BlockSize;
+ gSDMMCMedia.BlockSize = 512;
+ gSDMMCMedia.ReadOnly = 0;
+ gSDMMCMedia.MediaPresent = TRUE;
+ gSDMMCMedia.MediaId++;
+
+ UpdateMSHCClkFrequency(MSHC_CLK_50M);
+ DEBUG ((EFI_D_INFO, "SD Card Media Change on Handle 0x%08x\n", gImageHandle));
+
+ return Status;
+}
+
+
+EFI_STATUS
+SdReadWrite (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Lba,
+ OUT VOID *Buffer,
+ IN UINTN BufferSize,
+ IN OPERATION_TYPE OperationType
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN RetryCount = 0;
+ UINTN BlockCount;
+ UINTN BytesToBeTranferedThisPass = 0;
+ UINTN BytesRemainingToBeTransfered=0;
+ EFI_TPL OldTpl;
+ //BOOLEAN Update;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ if(gMediaChange==TRUE)
+ {
+ Status = DetectCard();
+ gMediaChange = FALSE;
+ gCardInit = TRUE;
+ }
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "MSHC::Card initialization fail .\n"));
+ gCardInit = FALSE;
+ goto Done;
+ }
+
+if(gCardInit)
+{
+ DEBUG ((EFI_D_INFO, "MSHC::SdReadWrite is called Buffersize:%d \n", BufferSize));
+
+ if (Buffer == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (Lba > This->Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((EFI_D_ERROR, "MSHC::SdReadWrite EFI_INVALID_PARAMETER\n"));
+ goto Done;
+ }
+
+ if ((BufferSize % This->Media->BlockSize) != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ DEBUG ((EFI_D_ERROR, "MSHC::SdReadWrite EFI_BAD_BUFFER_SIZE\n"));
+ goto Done;
+ }
+
+ //Check if the data lines are not in use.
+ while ((RetryCount++ < MAX_RETRY_COUNT) && (MmioRead32 ((SdMmcBaseAddr + MSHCI_STATUS)) & DATA_BUSY));
+ if (RetryCount == MAX_RETRY_COUNT) {
+ Status = EFI_TIMEOUT;
+ DEBUG ((EFI_D_ERROR, "MSHC::SdReadWrite EFI_TIMEOUT\n"));
+ goto Done;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ BytesRemainingToBeTransfered = BufferSize;
+
+ if(MSHC_operation_mode == MSHC_IDMA)
+ {
+ while (BytesRemainingToBeTransfered > 0) {
+ // Turn OFF DMA path until it is debugged
+ BytesToBeTranferedThisPass = (BytesRemainingToBeTransfered >= MAX_MSHC_TRANSFER_SIZE) ? MAX_MSHC_TRANSFER_SIZE : BytesRemainingToBeTransfered;
+ //BytesToBeTranferedThisPass = This->Media->BlockSize;
+
+ BlockCount = BytesToBeTranferedThisPass/This->Media->BlockSize;
+ Status = TransferBlock (This, Lba, Buffer,BlockCount, OperationType);
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));
+ goto DoneRestoreTPL;
+ }
+
+ BytesRemainingToBeTransfered -= BytesToBeTranferedThisPass;
+ Lba += BlockCount;
+ Buffer = (UINT8 *)Buffer + (This->Media->BlockSize*BlockCount);
+ DEBUG ((EFI_D_INFO, "SdReadWrite::Buf:0x%x, ToBe:0x%x Rema:0x%x \n", BufferSize, BytesToBeTranferedThisPass, BytesRemainingToBeTransfered));
+
+ }
+ }
+ else
+ {
+ while (BytesRemainingToBeTransfered > 0) {
+ // Turn OFF DMA path until it is debugged
+ // BytesToBeTranferedThisPass = (BytesToBeTranferedThisPass >= MAX_SDHC_TRANSFER_SIZE) ? MAX_SDHC_TRANSFER_SIZE : BytesRemainingToBeTransfered;
+ BytesToBeTranferedThisPass = This->Media->BlockSize;
+
+ BlockCount = BytesToBeTranferedThisPass/This->Media->BlockSize;
+
+ if (BlockCount > 1) {
+ // Status = DmaBlocks (This, Lba, Buffer, BlockCount, OperationType);
+ } else {
+ //Transfer a block worth of data.
+ Status = TransferBlock (This, Lba, Buffer, BlockCount,OperationType);
+
+ }
+
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status));
+ goto DoneRestoreTPL;
+ }
+
+ BytesRemainingToBeTransfered -= BytesToBeTranferedThisPass;
+ Lba += BlockCount;
+ Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
+ }
+
+ }
+
+
+DoneRestoreTPL:
+
+ gBS->RestoreTPL (OldTpl);
+
+Done:
+
+ return Status;
+}
+else
+ return EFI_TIMEOUT;
+
+
+}
+
+
+/**
+
+ Reset the Block Device.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+
+
+ @retval EFI_SUCCESS The device was reset.
+
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+
+ not be reset.
+
+
+
+**/
+EFI_STATUS
+EFIAPI
+MSHCReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ DEBUG ((EFI_D_INFO, " MSHC::MSHCReset is called\n"));
+ MSHC_reset_all();
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Read BufferSize bytes from Lba into Buffer.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+ @param MediaId Id of the media, changes every time the media is replaced.
+
+ @param Lba The starting Logical Block Address to read from
+
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+
+ responsible for either having implicit or explicit ownership of the buffer.
+
+
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+
+ or the buffer is not on proper alignment.
+
+EFI_STATUS
+
+**/
+
+
+#define EMMC_TEST 0
+#if EMMC_TEST
+#define EMMC_TEST_SIZE (MAX_MSHC_TRANSFER_SIZE+1024)
+UINT32 bWrite[EMMC_TEST_SIZE];
+UINT32 bRead[EMMC_TEST_SIZE];
+//INTN EFIAPI CompareMem (IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
+//two buffers are identical, then 0 is returned. Otherwise, the value returned is the first mismatched byte
+
+void MSHC_Test( IN EFI_BLOCK_IO_PROTOCOL *This)
+{
+ UINTN i=0;
+ UINTN Count;
+ INTN ret;
+ EFI_STATUS Status;
+ DEBUG ((EFI_D_INFO, "MSHC::Read Write test %dB\n", EMMC_TEST_SIZE));
+
+ for(i=0; i<EMMC_TEST_SIZE; i++)
+ {
+ bWrite[i]=i;
+ }
+
+//multi
+ for(Count=100; Count<102; Count++)
+ {
+ //Lba=n;
+ //DEBUG ((EFI_D_INFO, "MSHC::Read Write test : %d\n", Count));
+ ZeroMem (&bRead[0], sizeof(bRead));
+ DEBUG ((EFI_D_INFO, "ZR : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bRead[0], bRead[1], bRead[2], bRead[3]));
+
+ Status = SdReadWrite (This, (UINTN)Count, &bWrite[0], EMMC_TEST_SIZE, WRITE);
+ Status = SdReadWrite (This, (UINTN)Count, &bRead[0], EMMC_TEST_SIZE, READ);
+
+ DEBUG ((EFI_D_INFO, "W: 0x%x, 0x%x, 0x%x, 0x%x ",
+ bWrite[0], bWrite[1], bWrite[2], bWrite[3]));
+ DEBUG ((EFI_D_INFO, "R : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bRead[0], bRead[1], bRead[2], bRead[3]));
+
+ ret = CompareMem(&bRead[0],&bWrite[0],EMMC_TEST_SIZE);
+
+ if(ret==0)
+ DEBUG ((1, "MSHC::Read Write OK!!\n"));
+ else
+ DEBUG ((1, "MSHC::Read Write Failed bWrite[%d]=0x%x : bRead[%d]=0x%x\n", ret, bWrite[ret], ret, bRead[ret]));
+
+
+ }
+
+
+}
+#endif
+
+
+#define FVB_TEST 0
+
+#if FVB_TEST
+#define FVB_TEST_SIZE 1336//(64)
+#define FVB_Offset 64 //0
+UINT32 FVB_Read[512*3];
+UINT32 FVB_Write[512*3];
+UINT32 Temp[512*3];
+void FVB_Test(IN EFI_BLOCK_IO_PROTOCOL *This)
+{
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *Fvbhandle;
+ EFI_STATUS status = EFI_SUCCESS;
+ EFI_LBA Lba = 10;
+ UINTN NumBytes=FVB_TEST_SIZE;
+ UINT32 i;
+ INTN ret;
+ UINTN Offset=FVB_Offset;
+ //EFI_FVB_ATTRIBUTES_2 *Attribute=NULL;
+ UINTN blocksize=0, numofblocks=0;
+ UINTN EraseStartBlock=10, EraseNumBlocks=5;
+ EFI_PHYSICAL_ADDRESS *Address=NULL;
+
+
+ Fvbhandle = (EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *)This;
+ DEBUG ((1, "FVB_Test Start \n"));
+
+ status = SdReadWrite (This, 0, &Temp[0], 512, READ);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((1, "FVB_Test Card Init Failed !!\n"));
+ goto Exit;
+ }
+
+ for(i=0; i<512; i++)
+ {
+ FVB_Write[i]=i;
+ }
+ ZeroMem (&FVB_Read[0], 512);
+
+ //DEBUG ((1, "FVB_Test FvbGetAttributes \n"));
+ //FvbGetAttributes(Fvbhandle, Attribute);
+ FvbGetPhysicalAddress(Fvbhandle, Address);
+ FvbGetBlockSize(Fvbhandle, 0, &blocksize, &numofblocks);
+ DEBUG ((1, "FVB_Test erase\n"));
+ FvbEraseBlocks(Fvbhandle, EraseStartBlock, EraseNumBlocks, EFI_LBA_LIST_TERMINATOR);
+
+ DEBUG ((1, "FVB_Test Offset : %d Num : %d\n", Offset, NumBytes));
+ status = FvbWrite(Fvbhandle, Lba, Offset, &NumBytes, (UINT8 *)&FVB_Write[Offset]);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((1, "FVB_Test write fail !!\n"));
+ goto Exit;
+ }
+
+ status = FvbRead(Fvbhandle, Lba, Offset, &NumBytes, (UINT8 *)&FVB_Read[0]);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((1, "FVB_Test read fail !!\n"));
+ goto Exit;
+ }
+
+ DEBUG ((1, "FVB W: 0x%x, 0x%x, 0x%x, 0x%x ",
+ FVB_Write[Offset], FVB_Write[Offset+1], FVB_Write[Offset+2], FVB_Write[Offset+3]));
+ DEBUG ((1, "FVB R : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ FVB_Read[0], FVB_Read[1], FVB_Read[2], FVB_Read[3]));
+
+ ret = CompareMem(&FVB_Write[Offset], &FVB_Read[0], FVB_TEST_SIZE);
+
+ if(ret==0)
+ DEBUG ((1, "MSHC::FVB_Test OK!!\n"));
+ else
+ DEBUG ((1, "MSHC::ERROR !!! FVB_Test Failed bWrite[%d]=0x%x : bRead[%d]=0x%x\n", ret, FVB_Write[ret], ret, FVB_Read[ret]));
+
+ Exit:
+ if(status!=EFI_SUCCESS)
+ DEBUG ((1, "FVB_Test fail !!\n"));
+
+}
+
+#endif
+
+
+
+EFI_STATUS
+EFIAPI
+MSHCReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status=EFI_SUCCESS;
+ DEBUG ((EFI_D_INFO, "MSHC::MSHCReadBlocks : MediaId = %x, Lba = %d, BufferSize = %d, Buffer = 0x%x\n",
+ MediaId, (UINTN)Lba, BufferSize, Buffer));
+
+ Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, READ);
+
+#if 0
+#if FVB_TEST
+ FVB_Test(This);
+#else
+#if EMMC_TEST
+ MSHC_Test(This);
+#else
+ //Perform Read operation.
+ Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, READ);
+#endif
+#endif //#if FVB_TEST
+#endif
+
+ return Status;
+
+}
+
+
+/**
+
+ Write BufferSize bytes from Lba into Buffer.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+ @param MediaId The media ID that the write request is for.
+
+ @param Lba The starting logical block address to be written. The caller is
+
+ responsible for writing to only legitimate locations.
+
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+
+ @param Buffer A pointer to the source buffer for the data.
+
+
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+
+ or the buffer is not on proper alignment.
+
+
+
+**/
+
+
+EFI_STATUS
+EFIAPI
+MSHCWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+#if EMMC_TEST
+ UINT32 Count=0;
+ UINT32 ret;
+#endif
+
+ DEBUG ((EFI_D_INFO, "MSHC::MSHCWriteBlocks : MediaId = 0x%x, Lba = %d, BufferSize = %d, Buffer = 0x%x\n",
+ MediaId, (UINTN)Lba, BufferSize, Buffer));
+
+ //Perform write operation.
+ Status = SdReadWrite (This, (UINTN)Lba, Buffer, BufferSize, WRITE);
+
+
+#if 0
+#if EMMC_TEST
+ Count = (BufferSize >= MAX_MSHC_TRANSFER_SIZE) ? MAX_MSHC_TRANSFER_SIZE : BufferSize;
+ DEBUG ((1, "\nMSHC::Read Write Test [0x%x] Start \n", Count));
+ ZeroMem (&bRead[0], sizeof(bRead));
+ CopyMem(&bWrite[0], (VOID *)Buffer, Count);
+ Status = SdReadWrite (This, (UINTN)Lba, &bRead[0], Count, READ);
+ DEBUG ((1, "W : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bWrite[7], bWrite[8], bWrite[9], bWrite[10]));
+
+ DEBUG ((1, "R : 0x%x, 0x%x, 0x%x, 0x%x\n",
+ bRead[7], bRead[8], bRead[9], bRead[10]));
+
+ ret = CompareMem(&bRead[0],&bWrite[0],Count);
+
+ if(ret==0)
+ DEBUG ((1, "MSHC::Read Write Test OK!!\n"));
+ else
+ DEBUG ((1, "MSHC::Read Write Test Failed -.- bRead[%d]=0x%x bWrite[%d]=0x%x \n", ret, bRead[ret], ret, bWrite[ret]));
+
+#endif
+#endif
+
+
+ return Status;
+
+}
+
+
+/**
+
+ Flush the Block Device.
+
+
+
+ @param This Indicates a pointer to the calling context.
+
+
+
+ @retval EFI_SUCCESS All outstanding data was written to the device
+
+ @retval EFI_DEVICE_ERROR The device reported an error while writting back the data
+
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+
+
+**/
+EFI_STATUS
+EFIAPI
+MSHCFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ DEBUG ((EFI_D_INFO, "MSHC::MSHCFlushBlocks is called\n"));
+ return EFI_SUCCESS;
+}
+
+
+EFI_BLOCK_IO_PROTOCOL gBlockIo = {
+ EFI_BLOCK_IO_INTERFACE_REVISION, // Revision
+ &gSDMMCMedia, // *Media
+ MSHCReset, // Reset
+ MSHCReadBlocks, // ReadBlocks
+ MSHCWriteBlocks, // WriteBlocks
+ MSHCFlushBlocks // FlushBlocks
+};
+
+
+EFI_STATUS
+EFIAPI
+MSHCInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&gCardInfo, sizeof (CARD_INFO));
+
+//Publish BlockIO.
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiBlockIoProtocolGuid, &gBlockIo,
+ &gEfiDevicePathProtocolGuid, &gMSHCDevicePath,
+ NULL
+ );
+
+ DEBUG ((EFI_D_INFO, "MSHC::MSHCInitialize:0x%x\n", Status));
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.h
new file mode 100755
index 000000000..e410d669e
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.h
@@ -0,0 +1,308 @@
+/** @file
+
+ Copyright (c) 2011, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 _MSHCDXE_H_
+#define _MSHCDXE_H_
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#include "eMMCDxe_5250.h"
+#include "eMMCDxe_CMD.h"
+
+/**
+eMMC partition Gaia EVT1
+
+boot partition-1 : 100M store BL1, BL2, UEFI, TZSW
+boot partition-2 : 100M not used
+RPMB : 16M for secure team
+General purpose-1 : not used
+General purpose-2 : not used
+General purpose-3 : not used
+General purpose-4 : not used
+
+boot partition-1 start offset
+BL1: 0
+BL2: 16
+UEFI : 32
+TZSW : 2592~3104
+NV data area : 3200
+NV data for security team : 3200
+NV data for general purpose : 3400
+**/
+
+#define MSHC_BOOT_SIZE 100
+#define MSHC_RPMB_SIZE 0
+#define MSHC_BOOT_SIZE_MULTI (MSHC_BOOT_SIZE*2)
+#define MSHC_BOOT_SECURE_OFFSET 3200
+#define MSHC_BOOT_SECURE_SIZE 512 // 256k
+
+#define MSHC_BOOT_PARTITION 0
+#define MSHC_RPMB_PARTITION 1
+#define MSHC_USER_PARTITION 2
+
+#define BLEN_512BYTES (0x200)
+#define BLKSIZE_1 (0x1)
+
+#define OM_EMMC 0x8
+
+#define MAX_RETRY_COUNT (100000)
+#define MMC_REFERENCE_CLK (96000000)
+#define MSHC_CLK_400 (400)
+#define MSHC_CLK_25M (25000)
+#define MSHC_CLK_50M (50000)
+
+#define OCR_BUSY 0x80000000
+#define OCR_HCS 0x40000000
+
+#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
+#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
+#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */
+#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */
+#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */
+#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */
+#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */
+#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */
+#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */
+#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */
+#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */
+#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */
+#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */
+#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */
+#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */
+#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */
+#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
+
+
+#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
+#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in EXT_CSD byte
+ addressed by index which are
+ 1 in value field */
+#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits in EXT_CSD byte
+ addressed by index, which are
+ 1 in value field */
+#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target byte to value */
+/*
+ * EXT_CSD fields
+ */
+
+#define EXT_CSD_BUS_WIDTH 183 /* R/W */
+#define EXT_CSD_HS_TIMING 185 /* R/W */
+#define EXT_CSD_CARD_TYPE 196 /* RO */
+#define EXT_CSD_REV 192 /* RO */
+#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
+#define BOOT_SIZE_MULTI 226 /* RO */
+#define PARTITIONING_SUPPORT 160 /* RO */
+
+/*
+ * EXT_CSD field definitions
+ */
+
+/* Card */
+#define EXT_CSD_CMD_SET_NORMAL (1<<0)
+#define EXT_CSD_CMD_SET_SECURE (1<<1)
+#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
+
+#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
+#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_52_DDR_18_30 (1<<2) /* Card can run at 52MHz DDR 1.8V or 3V */
+#define EXT_CSD_CARD_TYPE_52_DDR_12 (1<<3) /* Card can run at 52MHz DDR 1.2V */
+
+#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
+#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
+#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
+#define EXT_CSD_BUS_WIDTH_4_DDR 5 /* Card is in 4 bit DDR mode */
+#define EXT_CSD_BUS_WIDTH_8_DDR 6 /* Card is in 8 bit DDR mode */
+
+
+typedef struct {
+ UINT32 hs_max_dtr;
+ UINT32 sectors;
+ UINT32 boot_size_multi; //226
+ UINT32 Partitioning_Support; //160
+}mmc_ext_csd;
+
+
+typedef struct {
+ UINT32 Reserved0: 7; // 0
+ UINT32 V170_V195: 1; // 1.70V - 1.95V
+ UINT32 V200_V260: 7; // 2.00V - 2.60V
+ UINT32 V270_V360: 9; // 2.70V - 3.60V
+ UINT32 RESERVED_1: 5; // Reserved
+ UINT32 AccessMode: 2; // 00b (byte mode), 10b (sector mode)
+ UINT32 Busy: 1; // This bit is set to LOW if the card has not finished the power up routine
+}OCR;
+
+typedef struct {
+ UINT32 NOT_USED; // 1 [0:0]
+ UINT32 CRC; // CRC7 checksum [7:1]
+ UINT32 MDT; // Manufacturing date [19:8]
+ UINT32 RESERVED_1; // Reserved [23:20]
+ UINT32 PSN; // Product serial number [55:24]
+ UINT8 PRV; // Product revision [63:56]
+ UINT8 PNM[5]; // Product name [64:103]
+ UINT16 OID; // OEM/Application ID [119:104]
+ UINT8 MID; // Manufacturer ID [127:120]
+}CID;
+
+typedef struct {
+ UINT8 NOT_USED: 1; // Not used, always 1 [0:0]
+ UINT8 CRC: 7; // CRC [7:1]
+
+ UINT8 RESERVED_1: 2; // Reserved [9:8]
+ UINT8 FILE_FORMAT: 2; // File format [11:10]
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]
+
+ UINT16 RESERVED_2: 5; // Reserved [20:16]
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]
+ UINT16 RESERVED_3: 2; // Reserved [30:29]
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]
+
+ UINT32 WP_GRP_SIZE: 7; // Write protect group size [38:32]
+ UINT32 SECTOR_SIZE: 7; // Erase sector size [45:39]
+ UINT32 ERASE_BLK_EN: 1; // Erase single block enable [46:46]
+ UINT32 C_SIZE_MULT: 3; // Device size multiplier [49:47]
+ UINT32 VDD_W_CURR_MAX: 3; // Max. write current @ VDD max [52:50]
+ UINT32 VDD_W_CURR_MIN: 3; // Max. write current @ VDD min [55:53]
+ UINT32 VDD_R_CURR_MAX: 3; // Max. read current @ VDD max [58:56]
+ UINT32 VDD_R_CURR_MIN: 3; // Max. read current @ VDD min [61:59]
+ UINT32 C_SIZELow2: 2; // Device size [63:62]
+
+ UINT32 C_SIZEHigh10: 10;// Device size [73:64]
+ UINT32 RESERVED_4: 2; // Reserved [75:74]
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]
+ UINT32 READ_BL_LEN: 4; // Max. read data block length [83:80]
+ UINT32 CCC: 12;// Card command classes [95:84]
+
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+ UINT8 TAAC ; // Data read access-time 1 [119:112]
+
+ UINT8 RESERVED_5: 6; // Reserved [125:120]
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
+}CSD;
+
+
+
+typedef struct {
+ UINT8 NOT_USED: 1; // Not used, always 1 [0:0]
+ UINT8 CRC: 7; // CRC [7:1]
+ UINT8 RESERVED_1: 2; // Reserved [9:8]
+ UINT8 FILE_FORMAT: 2; // File format [11:10]
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]
+ UINT16 RESERVED_2: 5; // Reserved [20:16]
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]
+ UINT16 RESERVED_3: 2; // Reserved [30:29]
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]
+ UINT16 WP_GRP_SIZE: 7; // Write protect group size [38:32]
+ UINT16 SECTOR_SIZE: 7; // Erase sector size [45:39]
+ UINT16 ERASE_BLK_EN: 1; // Erase single block enable [46:46]
+ UINT16 RESERVED_4: 1; // Reserved [47:47]
+ UINT32 C_SIZELow16: 16;// Device size [69:48]
+ UINT32 C_SIZEHigh6: 6; // Device size [69:48]
+ UINT32 RESERVED_5: 6; // Reserved [75:70]
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]
+ UINT16 READ_BL_LEN: 4; // Max. read data block length [83:80]
+ UINT16 CCC: 12;// Card command classes [95:84]
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+ UINT8 TAAC ; // Data read access-time 1 [119:112]
+ UINT8 RESERVED_6: 6; // 0 [125:120]
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
+}CSD_SDV2;
+
+typedef enum {
+ UNKNOWN_CARD,
+ MMC_CARD, //MMC card
+ SD_CARD, //SD 1.1 card
+ SD_CARD_2, //SD 2.0 or above standard card
+ SD_CARD_2_HIGH, //SD 2.0 or above high capacity card
+ SD_CARD_MAX
+} CARD_TYPE;
+
+
+
+typedef enum {
+ MSHC_IDMA,
+ MSHC_FIFO
+}MSHC_OPERATION_MODE;
+
+typedef struct {
+ UINT16 RCA;
+ UINTN BlockSize;
+ UINTN NumBlocks;
+ UINTN TotalNumBlocks;
+ UINTN ClockFrequencySelect;
+ CARD_TYPE CardType;
+ OCR OCRData;
+ CID CIDData;
+ CSD CSDData;
+ mmc_ext_csd Extcsd;
+} CARD_INFO;
+
+
+EFI_STATUS
+DetectCard (VOID);
+void mshci_reset_fifo(void);
+
+extern EFI_BLOCK_IO_PROTOCOL gBlockIo;
+extern EFI_BLOCK_IO_MEDIA gSDMMCMedia;
+extern CARD_INFO gCardInfo;
+extern BOOLEAN gCardInit;
+
+extern EFI_STATUS
+SdReadWrite (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINTN Lba,
+ OUT VOID *Buffer,
+ IN UINTN BufferSize,
+ IN OPERATION_TYPE OperationType
+ );
+EFI_STATUS
+EraseBlockData (
+ IN UINT32 Partition,
+ IN UINTN StartBlock,
+ IN UINTN NumBlock
+ );
+
+
+
+#endif
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.inf
new file mode 100755
index 000000000..45e9ed1a4
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.inf
@@ -0,0 +1,64 @@
+#/** @file
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = eMMCDxe
+ FILE_GUID = 39ad4d3f-dee8-4708-ac4e-46c8335c48a6
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = MSHCInitialize
+
+
+[Sources.common]
+ eMMCDxe.c
+ eMMCDxe_5250.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+ SamsungPlatformPkg/SamsungPlatformPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ IoLib
+ TimerLib
+ MemoryAllocationLib
+ UncachedMemoryAllocationLib
+
+[Guids]
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gSamsungPlatformGpioProtocolGuid ## GPIO Protocol
+ gEfiFirmwareVolumeBlockProtocolGuid
+
+[Pcd]
+ gExynosPkgTokenSpaceGuid.PcdCmuBase
+ gExynosPkgTokenSpaceGuid.PcdSdMmcCH0Base
+ gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferBase
+
+[FixedPcd.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+
+[Depex]
+ TRUE
+
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_5250.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_5250.c
new file mode 100755
index 000000000..511b079d4
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_5250.c
@@ -0,0 +1,721 @@
+/** @file
+ MMC/SD Card driver for Secure Digital Host Controller
+
+ This driver always produces a BlockIo protocol but it starts off with no Media
+ present. A TimerCallBack detects when media is inserted or removed and after
+ a media change event a call to BlockIo ReadBlocks/WriteBlocks will cause the
+ media to be detected (or removed) and the BlockIo Media structure will get
+ updated. No MMC/SD Card harward registers are updated until the first BlockIo
+ ReadBlocks/WriteBlocks after media has been insterted (booting with a card
+ plugged in counts as an insertion event).
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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/TimerLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UncachedMemoryAllocationLib.h>
+#include <Protocol/ExynosGpio.h>
+#include <Platform/ArmPlatform.h>
+#include <Platform/Exynos5250.h>
+#include <Platform/Arndale5250.h>
+
+
+#include "eMMCDxe.h"
+
+//#undef EFI_D_INFO
+//#define EFI_D_INFO 1
+
+#define DMA_UNCACHE_ALLOC 0
+#if DMA_UNCACHE_ALLOC
+UINT32 *DMABuffer;
+#endif
+void MSHC_reset_all(void)
+{
+ int count;
+ volatile int ctl_val=0;
+ UINT32 SdMmcBaseAddr;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ /* Wait max 100 ms */
+ count = 10000;
+
+ /* before reset ciu, it should check DATA0. if when DATA0 is low and
+ it resets ciu, it might make a problem */
+ while ((MmioRead32 ((SdMmcBaseAddr + MSHCI_STATUS)) & (1<<9))){
+ if (count == 0) {
+ DEBUG ((EFI_D_ERROR, "MMC controller never released. \n"));
+ return;
+ }
+ count--;
+ MicroSecondDelay(1);
+ }
+
+ // Reset CIU
+ ctl_val = MmioRead32((SdMmcBaseAddr + MSHCI_CTRL));
+ ctl_val |= CTRL_RESET;
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), ctl_val);
+
+ //Reset FIFO
+ MSHC_reset_fifo();
+
+ //Reset DMA
+ ctl_val = MmioRead32((SdMmcBaseAddr + MSHCI_CTRL));
+ ctl_val |= DMA_RESET;
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), ctl_val);
+
+ //Set auto stop CMD
+ ctl_val = MmioRead32((SdMmcBaseAddr + MSHCI_CTRL));
+ ctl_val |= SEND_AS_CCSD;
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), ctl_val);
+
+}
+
+
+void MSHC_Set_DDR(int BusMode)
+{
+
+ UINT32 clkphase;
+ //clkphase = 0x03030002; //cmd response error at 50M RINT=0x46 error, RE and CD, RCRC
+ //clkphase = 0x03020001; //data read error at 50M SBE
+ UINT32 SdMmcBaseAddr;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ if(BusMode==BUSMODE_DDR)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC DDR .\n"));
+ MmioWrite32((SdMmcBaseAddr + MSHCI_UHS_REG), UHS_DDR);
+ clkphase = 0x03020001;
+ }
+ else
+ {
+ DEBUG ((EFI_D_INFO, "MSHC Non DDR .\n"));
+ MmioWrite32((SdMmcBaseAddr + MSHCI_UHS_REG), UHS_NON_DDR);
+ clkphase = 0x03030002;
+ }
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CLKSEL), clkphase);
+
+}
+
+
+void MSHC_5250_init(void)
+{
+ UINT32 SdMmcBaseAddr;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ /* Power Enable Register */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_PWREN), POWER_ENABLE);
+ //MSHC_Set_DDR(BUSMODE_DDR);
+
+ MSHC_reset_all();
+
+ // Initialize FIFO
+ MmioWrite32((SdMmcBaseAddr + MSHCI_FIFOTH), (MSIZE_8 | TX_WMARK_DEFAULT | RX_WMARK_DEFAULT));
+
+ /* It clears all pending interrupts */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_RINTSTS), INTMSK_ALL);
+ /* It dose not use Interrupt. Disable all */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_INTMSK), 0);
+
+ //UpdateMSHCClkFrequency(MSHC_CLK_400);
+
+ /* Set auto stop command */
+ //MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), (1<<10));
+
+ /* set debounce filter value*/
+ MmioWrite32((SdMmcBaseAddr + MSHCI_DEBNCE), (0xfffff));
+
+ /* clear card type. set 1-bit mode */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTYPE), 0x0);
+
+ /* set bus mode register for IDMAC */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_BMOD), (BMOD_IDMAC_RESET));
+
+ /* disable all interrupt source of IDMAC */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_IDINTEN), (0x0));
+
+ /* set max timeout */
+ MmioWrite32((SdMmcBaseAddr + MSHCI_TMOUT), (0xffffffff));
+
+ MmioWrite32((SdMmcBaseAddr + MSHCI_BLKSIZ), BLEN_512BYTES);
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CLKSEL), 0x03030002);
+
+}
+
+EFI_STATUS
+InitializeMSHC (
+ VOID
+ )
+{
+
+ EFI_STATUS Status;
+ EXYNOS_GPIO *Gpio;
+ UINT32 CumBaseAddr;
+ //UINT32 SdMmcBaseAddr;
+ UINT32 i, clock;
+ volatile UINT32 ctl_val;
+
+
+ Status = gBS->LocateProtocol(&gSamsungPlatformGpioProtocolGuid, NULL, (VOID **)&Gpio);
+ ASSERT_EFI_ERROR(Status);
+
+ CumBaseAddr = PcdGet32(PcdCmuBase);
+ //SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ //MmioWrite32((SdMmcBaseAddr + SDHC_SWRST_OFFSET), SRA);
+
+ // Set Clock Source for using MPLL
+ ctl_val = MmioRead32((CumBaseAddr + CLK_SRC_FSYS_OFFSET));
+ ctl_val &= ~(0xf);
+ ctl_val |= (0x6);
+ MmioWrite32((CumBaseAddr + CLK_SRC_FSYS_OFFSET), ctl_val);
+ //MmioAndThenOr32 ((CumBaseAddr + CLK_SRC_FSYS_OFFSET), ~(0xF), (0x6));
+
+ // CLK mask
+ ctl_val = MmioRead32((CumBaseAddr + CLK_SRC_MASK_FSYS_OFFSET));
+ ctl_val |= (0x1);
+ MmioWrite32((CumBaseAddr + CLK_SRC_MASK_FSYS_OFFSET), ctl_val);
+
+ // CLK gating
+ ctl_val = MmioRead32((CumBaseAddr + CLK_GATE_IP_FSYS_OFFSET));
+ ctl_val |= (0x1<<12);
+ MmioWrite32((CumBaseAddr + CLK_GATE_IP_FSYS_OFFSET), ctl_val);
+
+
+ /* MMC2 clock div */
+ clock = 800; //MPLL in MHz
+ for(i=0; i<= 0xf; i++)
+ {
+ if((clock / (i+1)) <= 90) {
+ MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS1_OFFSET), ~(0xF << 0), (i << 0));
+ break;
+ }
+ }
+
+
+ // 2. GPIO setting
+ // Set GPIO for using SD/MMC CH0 for eMMC
+ Gpio->Set(Gpio,SD_0_CLK,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_0_CMD,GPIO_MODE_SPECIAL_FUNCTION_2);
+ //Gpio->Set(Gpio,SD_0_CDn,GPIO_MODE_SPECIAL_FUNCTION_2);
+
+ //Set CDn as HIGH
+ Gpio->Set(Gpio,SD_0_CDn, GPIO_MODE_OUTPUT_1);
+
+
+ Gpio->Set(Gpio,SD_0_DATA0,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_0_DATA1,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_0_DATA2,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_0_DATA3,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_0_DATA4,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_0_DATA5,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_0_DATA6,GPIO_MODE_SPECIAL_FUNCTION_2);
+ Gpio->Set(Gpio,SD_0_DATA7,GPIO_MODE_SPECIAL_FUNCTION_2);
+
+ Gpio->SetPull(Gpio,SD_0_CLK,GPIO_PULL_NONE);
+ Gpio->SetPull(Gpio,SD_0_CMD,GPIO_PULL_NONE);
+ Gpio->SetPull(Gpio,SD_0_CDn,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_0_DATA0,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_0_DATA1,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_0_DATA2,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_0_DATA3,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_0_DATA4,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_0_DATA5,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_0_DATA6,GPIO_PULL_UP);
+ Gpio->SetPull(Gpio,SD_0_DATA7,GPIO_PULL_UP);
+
+Gpio->SetStrength(Gpio,SD_0_CLK,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_CMD,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_CDn,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_DATA0,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_DATA1,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_DATA2,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_DATA3,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_DATA4,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_DATA5,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_DATA6,GPIO_DRV_3X);
+Gpio->SetStrength(Gpio,SD_0_DATA7,GPIO_DRV_3X);
+
+ MSHC_5250_init();
+#if DMA_UNCACHE_ALLOC
+ DMABuffer = (UINT32 *)UncachedAllocatePool(EMMC_DMA_PHYSICAL_BUFFER_SIZE/2);
+ if(DMABuffer==NULL)
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC::DMA alloc failed \n"));
+ }
+#endif
+ return EFI_SUCCESS;
+
+}
+
+void MSHC_reset_fifo(void)
+{
+ volatile int ctl_val=0;
+ UINT32 SdMmcBaseAddr;
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+ //Reset FIFO
+ ctl_val = MmioRead32((SdMmcBaseAddr + MSHCI_CTRL));
+ ctl_val |= FIFO_RESET;
+ MmioWrite32((SdMmcBaseAddr + MSHCI_CTRL), ctl_val);
+
+}
+
+
+VOID MSHC_clock_onoff (int value)
+{
+ volatile UINT32 loop_count = 0x100000;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ if(value==CLK_ENABLE)
+ {
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKENA), (0x1<<0));
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), 0);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), CMD_ONLY_CLK);
+ do {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_CMD) & CMD_STRT_BIT)==0)
+ break;
+ loop_count--;
+ } while (loop_count);
+ }
+ else
+ {
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKENA), (0x0<<0));
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), 0);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), CMD_ONLY_CLK);
+ do {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_CMD) & CMD_STRT_BIT)==0)
+ break;
+ loop_count--;
+ } while (loop_count);
+ }
+
+ if (loop_count == 0) {
+ DEBUG ((EFI_D_ERROR, "MSHC::clockonoff : Clk = %d\n", value));
+ }
+
+}
+
+
+VOID
+UpdateMSHCClkFrequency (
+ UINTN NewCLK
+ )
+{
+ UINT32 CumBaseAddr;
+ UINT32 SdMmcBaseAddr;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+ CumBaseAddr = PcdGet32(PcdCmuBase);
+
+ // Disable all clocks to not provide the clock to the card
+//(CONFIG_CPU_EXYNOS5250_EVT1)
+ MSHC_clock_onoff(CLK_DISABLE);
+ //MmioAnd32 ((SdMmcBaseAddr + CLKCON_OFFSET), ~(0xF));
+
+ //Set new clock frequency.
+ if (NewCLK == MSHC_CLK_400)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::CLK=400.\n"));
+ // MPLL=800, cclk_in=100, 100M/250=400k
+ //MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS1_OFFSET), ~(0xFFFF), 0xE008);
+ MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS1_OFFSET), ~(0xFFFF), 0x1);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKDIV), 125);
+ }
+ else if (NewCLK == MSHC_CLK_25M)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::CLK=25M.\n"));
+ // DDR mode use CLKDIV MPLL = 800, SCLK = 400, cclk_in=100M
+ MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS1_OFFSET), ~(0xFFFF), 0x1);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKDIV), 2);
+ }
+ else if(NewCLK == MSHC_CLK_50M)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::CLK=50M.\n"));
+ // DDR mode use CLKDIV MPLL = 800, SCLK = 400, cclk_in=100M
+ MmioAndThenOr32 ((CumBaseAddr + CLK_DIV_FSYS1_OFFSET), ~(0xFFFF), 0x1);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CLKDIV), 1);
+
+ MSHC_Set_DDR(BUSMODE_DDR);
+ //MmioWrite32 ((SdMmcBaseAddr + MSHCI_CMD), CMD_ONLY_CLK);
+ }
+
+//#if defined(CONFIG_CPU_EXYNOS5250_EVT1)
+ MSHC_clock_onoff(CLK_ENABLE);
+ //MmioOr32 ((SdMmcBaseAddr + CLKCON_OFFSET), ICE);
+
+ //Poll till Internal Clock Stable
+ //while ((MmioRead32 ((SdMmcBaseAddr + CLKCON_OFFSET)) & ICS) != ICS);
+
+ //Set Clock enable to 0x1 to provide the clock to the card
+ //MmioOr32 ((SdMmcBaseAddr + CLKCON_OFFSET), CCE);
+
+}
+
+extern MSHC_OPERATION_MODE MSHC_operation_mode;
+void mshci_set_mdma_desc(UINT8 *desc_vir, UINT8 *desc_phy,
+ UINT32 des0, UINT32 des1, UINT32 des2)
+{
+ ((struct mshci_idmac *)(desc_vir))->des0 = des0;
+ ((struct mshci_idmac *)(desc_vir))->des1 = des1;
+ ((struct mshci_idmac *)(desc_vir))->des2 = des2;
+ ((struct mshci_idmac *)(desc_vir))->des3 = (UINT32)desc_phy +
+ sizeof(struct mshci_idmac);
+}
+
+
+VOID
+PrepareTransfer (
+IN OUT VOID *Buffer, UINTN BlockCount, IN OPERATION_TYPE OperationType
+ )
+{
+ UINT32 SdMmcBaseAddr;
+ UINT32 EmmcDMABufferBase;
+ volatile UINT32 MshcRegValue;
+ struct mshci_idmac *pdesc_dmac;
+ UINT32 des_flag;
+ UINTN i=0;
+ UINT32 ByteCnt=0;
+ UINT32 BlockCnt=BlockCount;
+// UINT32 MSH_uDES_A_0, MSH_uDES_A_1, MSH_uDES_A_2, MSH_uDES_A_3;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+#if DMA_UNCACHE_ALLOC
+ EmmcDMABufferBase = (UINT32)DMABuffer;
+#else
+ EmmcDMABufferBase = PcdGet32(PcdEmmcDMABufferBase);
+#endif
+ //pdesc_dmac = idmac_desc;
+ pdesc_dmac = (struct mshci_idmac *)EmmcDMABufferBase;
+
+ if(MSHC_operation_mode==MSHC_FIFO)
+ {
+ MSHC_reset_fifo();
+
+ // 1. enable interrupt mode
+ MshcRegValue = MmioRead32(SdMmcBaseAddr + MSHCI_CTRL);
+ MshcRegValue |= INT_ENABLE;
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CTRL), MshcRegValue);
+
+ // 2. DDR mode
+
+ // 3. set BLKSIZE
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BLKSIZ), BLEN_512BYTES);
+ //MmioWrite32 ((SdMmcBaseAddr + MSHCI_BLKSIZ), BLKSIZE_1);
+
+ // 4. set BYTCNT
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BYTCNT), BLEN_512BYTES);
+
+ //Setting Data timeout counter value to max value.
+ MmioWrite32((SdMmcBaseAddr + MSHCI_TMOUT), (0xffffffff));
+
+ }
+ else if(MSHC_operation_mode==MSHC_IDMA)
+ {
+ ZeroMem ((VOID *)EmmcDMABufferBase, PHY_BUF_OFFSET);//20120608
+ if(OperationType==WRITE)
+ {
+ CopyMem((VOID *)(EmmcDMABufferBase+PHY_BUF_OFFSET), (VOID *)Buffer, BlockCount*BLEN_512BYTES);
+ //DEBUG ((EFI_D_INFO, "MSHC_DMA prepare WRITE:%d Block \n", BlockCount));
+ }
+ else
+ {
+ //DEBUG ((EFI_D_INFO, "MSHC_DMA prepare READ:%d Block \n", BlockCount));
+ }
+
+ MSHC_reset_fifo();
+
+ //IDMA reset
+ MshcRegValue = MmioRead32(SdMmcBaseAddr + MSHCI_BMOD);
+ MshcRegValue |= (BMOD_IDMAC_RESET);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BMOD), MshcRegValue);
+
+
+ // 1. enable IDMA at CTRL
+ MshcRegValue = MmioRead32(SdMmcBaseAddr + MSHCI_CTRL);
+ MshcRegValue &= ~(INT_ENABLE);
+ MshcRegValue |= (ENABLE_IDMAC);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_CTRL), MshcRegValue);
+
+
+ // 2. enable IDMA at BMODE
+ //Set Block Size and Block count.
+ MshcRegValue = MmioRead32(SdMmcBaseAddr + MSHCI_BMOD);
+ MshcRegValue |= (BMOD_IDMAC_ENABLE | BMOD_IDMAC_FB);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BMOD), MshcRegValue);
+
+ // interrupt enable
+ MmioWrite32((SdMmcBaseAddr + MSHCI_IDINTEN), (0x337));
+
+#if 0
+#if 0
+ // set descriptor singlechain
+ des_flag = 0x8000000E;
+ MSH_uDES_A_0 = (EmmcDMABufferBase+0x02F000);
+ MSH_uDES_A_1 = (EmmcDMABufferBase+0x02F004);
+ MSH_uDES_A_2 = (EmmcDMABufferBase+0x02F008);
+ MSH_uDES_A_3 = (EmmcDMABufferBase+0x02F00C);
+ MmioWrite32(MSH_uDES_A_0, 0x8000000E);
+ MmioWrite32(MSH_uDES_A_1, (ByteCount));
+ MmioWrite32(MSH_uDES_A_2, (EmmcDMABufferBase+PHY_BUF_OFFSET));
+ MmioWrite32(MSH_uDES_A_3, MSH_uDES_A_0);
+#endif
+
+
+
+ des_flag = (MSHCI_IDMAC_OWN | MSHCI_IDMAC_FS | MSHCI_IDMAC_DIC | MSHCI_IDMAC_LD);
+ mshci_set_mdma_desc((UINT8 *)pdesc_dmac,
+ (UINT8 *)pdesc_dmac,
+ des_flag, ByteCount,
+ ((UINT32)(EmmcDMABufferBase + PHY_BUF0_OFFSET)));
+
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_DBADDR), (UINT32)pdesc_dmac);
+
+
+
+#else
+
+ for(i=0; ; i++)
+ {
+ // set descriptor multichain
+ des_flag = (MSHCI_IDMAC_OWN|MSHCI_IDMAC_CH);
+ des_flag |= (i==0) ? MSHCI_IDMAC_FS:0;
+ if(BlockCnt<=8)
+ {
+ //DEBUG ((EFI_D_INFO, "DESC LD\n"));
+ des_flag |= (MSHCI_IDMAC_LD);
+ mshci_set_mdma_desc((UINT8 *)pdesc_dmac,
+ //(UINT8 *)pdesc_dmac,
+ (UINT8 *)(EmmcDMABufferBase-sizeof(struct mshci_idmac)),
+ des_flag, BlockCnt*BLEN_512BYTES,
+ ((UINT32)((EmmcDMABufferBase + PHY_BUF_OFFSET)+(UINT32)(i*PHY_BUF_SIZE))));
+ break;
+
+ }
+ //DEBUG ((EFI_D_INFO, "DESC FS\n"));
+ mshci_set_mdma_desc((UINT8 *)pdesc_dmac,
+ (UINT8 *)pdesc_dmac,
+ des_flag, BLEN_512BYTES*8,
+ ((UINT32)((EmmcDMABufferBase + PHY_BUF_OFFSET)+(UINT32)(i*PHY_BUF_SIZE))));
+
+ BlockCnt -=8;
+ pdesc_dmac++;
+
+ }
+
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_DBADDR), (UINT32)EmmcDMABufferBase);
+
+#endif
+
+ // 3. set BLKSIZE
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BLKSIZ), BLEN_512BYTES);
+
+ // 4. set BYTCNT
+ ByteCnt = (BlockCount*BLEN_512BYTES);
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_BYTCNT), ByteCnt);
+
+ //Setting Data timeout counter value to max value.
+ MmioWrite32((SdMmcBaseAddr + MSHCI_TMOUT), (0xffffffff));
+ DEBUG ((EFI_D_INFO, "Block:%d BYTCNT:0x%x ByteCnt:0x%x\n", BlockCount,MmioRead32(SdMmcBaseAddr + MSHCI_BYTCNT), ByteCnt));
+
+ }
+
+}
+
+EFI_STATUS MSHC_ReadFIFO(IN UINTN Size32, OUT VOID *Buffer)
+{
+ EFI_STATUS Status;
+ UINT32 SdMmcBaseAddr;
+ UINTN *DataBuffer = Buffer;
+ UINTN BufSize=Size32;
+ UINTN FifoCount=0;
+ UINTN Count=0;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+ //Check controller status to make sure there is no error.
+
+ while (BufSize)
+ {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & INTMSK_RXDR)
+ {
+
+ //Read block worth of data.
+ FifoCount = GET_FIFO_COUNT(MmioRead32 (SdMmcBaseAddr + MSHCI_STATUS));
+ DEBUG ((EFI_D_INFO, "MSHC::ReadBlock DTO FIFO:%d\n", FifoCount));
+ for (Count = 0; Count < FifoCount; Count++)
+ {
+ *DataBuffer++ = MmioRead32 (SdMmcBaseAddr + MSHCI_FIFO);
+ }
+ MmioWrite32((SdMmcBaseAddr + MSHCI_RINTSTS), INTMSK_RXDR);
+ BufSize -= FifoCount;
+ }
+
+ else if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & INTMSK_DTO)
+ {
+
+ //Read block worth of data.
+ FifoCount = GET_FIFO_COUNT(MmioRead32 (SdMmcBaseAddr + MSHCI_STATUS));
+ DEBUG ((EFI_D_INFO, "MSHC::ReadBlock DTO FIFO:%d\n", FifoCount));
+ for (Count = 0; Count < FifoCount; Count++)
+ {
+ *DataBuffer++ = MmioRead32 (SdMmcBaseAddr + MSHCI_FIFO);
+ }
+ MmioWrite32((SdMmcBaseAddr + MSHCI_RINTSTS), INTMSK_DTO);
+ BufSize -= FifoCount;
+ }
+
+ else if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & (INTMSK_DCRC|INTMSK_DRTO|INTMSK_HTO|INTMSK_FRUN))
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::ReadBlock Error RINT:0x%x\n", MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)));
+ return EFI_DEVICE_ERROR;
+ }
+
+ }
+
+ if(BufSize==0)
+ {
+ Status = EFI_SUCCESS;
+ }
+ else
+ {
+ Status = EFI_BAD_BUFFER_SIZE;
+ }
+ return Status;
+}
+
+EFI_STATUS MSHC_WriteFIFO(IN UINTN Size32, IN VOID *Buffer)
+{
+ UINT32 SdMmcBaseAddr;
+ UINTN *DataBuffer = Buffer;
+ UINTN BufSize=Size32;
+ UINTN Count=0;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+
+ if(BufSize>FIFO_SIZE)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC::Error MSHC_WriteFIFO Bad buffer size\n"));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ //Write block worth of data.
+ for (Count = 0; Count < BufSize; Count++)
+ {
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_FIFO), *DataBuffer++);
+ }
+ return EFI_SUCCESS;
+
+}
+
+/*typedef
+VOID
+CopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ );*/
+
+EFI_STATUS MSHC_ReadDMA(OUT VOID *Buffer, IN UINTN BlockCount)
+{
+ EFI_STATUS Status;
+ UINT32 SdMmcBaseAddr;
+ UINT32 EmmcDMABufferBase;
+ UINTN Count=MAX_RETRY_COUNT;
+ //UINT32 MshcRegValue;
+ //UINT32 TransferSize=0;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+#if DMA_UNCACHE_ALLOC
+ EmmcDMABufferBase = (UINT32)DMABuffer;
+#else
+ EmmcDMABufferBase = PcdGet32(PcdEmmcDMABufferBase);
+#endif
+ //Check controller status to make sure there is no error.
+
+ while (Count)
+ {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & INTMSK_DTO)
+ {
+ //TransferSize = MmioRead32 (SdMmcBaseAddr + MSHCI_TBBCNT);
+ CopyMem((VOID *)Buffer, (VOID *)(EmmcDMABufferBase+PHY_BUF_OFFSET), BlockCount*BLEN_512BYTES);
+ DEBUG ((EFI_D_INFO, "MSHC_ReadDMA Over %d Blocks\n", BlockCount));
+ break;
+ }
+ else if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & (DATA_ERR|DATA_TOUT))
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC_ReadDMA Err RINT:0x%x\n", MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)));
+ }
+
+ else
+ {
+ Count--;
+ MicroSecondDelay(1);
+ DEBUG ((EFI_D_INFO, ".\n"));
+ }
+
+ }
+
+ if(Count!=0)
+ {
+ Status = EFI_SUCCESS;
+ }
+ else
+ {
+ DEBUG ((EFI_D_ERROR, "MSHC_ReadDMA bad buffer size RINT:0x%x\n", MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)));
+ Status = EFI_BAD_BUFFER_SIZE;
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_PLDMND), 7);
+
+ }
+ return Status;
+}
+
+EFI_STATUS MSHC_WriteDMA(IN VOID *Buffer, IN UINTN BlockCount)
+{
+ EFI_STATUS Status;
+ UINT32 SdMmcBaseAddr;
+ UINTN Count=MAX_RETRY_COUNT;
+
+ SdMmcBaseAddr = PcdGet32(PcdSdMmcCH0Base);
+ //Check controller status to make sure there is no error.
+
+ while (Count)
+ {
+ if((MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)) & INTMSK_DTO)
+ {
+ DEBUG ((EFI_D_INFO, "MSHC_writeDMA Over %d blocks\n", BlockCount));
+ break;
+ }
+ else
+ {
+ MicroSecondDelay(1);
+ Count--;
+ }
+
+ }
+
+ if(Count!=0)
+ {
+ Status = EFI_SUCCESS;
+ }
+ else
+ {
+ Status = EFI_BAD_BUFFER_SIZE;
+ MmioWrite32 ((SdMmcBaseAddr + MSHCI_PLDMND), 7);
+ DEBUG ((EFI_D_ERROR, "MSHC_writeDMA bad buffer size RINT:0x%x \n", MmioRead32 (SdMmcBaseAddr + MSHCI_RINTSTS)));
+ }
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_5250.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_5250.h
new file mode 100755
index 000000000..56638ba44
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_5250.h
@@ -0,0 +1,322 @@
+/** @file
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 _MSHCDXE_5250_H_
+#define _MSHCDXE_5250_H_
+
+
+/*
+ * Controller registers
+ */
+/*****************************************************/
+/* MSHC Internal Registers */
+/*****************************************************/
+
+#define MSHCI_CTRL 0x00 /* Control */
+#define MSHCI_PWREN 0x04 /* Power-enable */
+#define MSHCI_CLKDIV 0x08 /* Clock divider */
+#define MSHCI_CLKSRC 0x0C /* Clock source */
+#define MSHCI_CLKENA 0x10 /* Clock enable */
+#define MSHCI_TMOUT 0x14 /* Timeout */
+#define MSHCI_CTYPE 0x18 /* Card type */
+#define MSHCI_BLKSIZ 0x1C /* Block Size */
+#define MSHCI_BYTCNT 0x20 /* Byte count */
+#define MSHCI_INTMSK 0x24 /* Interrupt Mask */
+#define MSHCI_CMDARG 0x28 /* Command Argument */
+#define MSHCI_CMD 0x2C /* Command */
+#define MSHCI_RESP0 0x30 /* Response 0 */
+#define MSHCI_RESP1 0x34 /* Response 1 */
+#define MSHCI_RESP2 0x38 /* Response 2 */
+#define MSHCI_RESP3 0x3C /* Response 3 */
+#define MSHCI_MINTSTS 0x40 /* Masked interrupt status */
+#define MSHCI_RINTSTS 0x44 /* Raw interrupt status */
+#define MSHCI_STATUS 0x48 /* Status */
+#define MSHCI_FIFOTH 0x4C /* FIFO threshold */
+#define MSHCI_CDETECT 0x50 /* Card detect */
+#define MSHCI_WRTPRT 0x54 /* Write protect */
+#define MSHCI_GPIO 0x58 /* General Purpose IO */
+#define MSHCI_TCBCNT 0x5C /* Transferred CIU byte count */
+#define MSHCI_TBBCNT 0x60 /* Transferred host/DMA to/from byte count */
+#define MSHCI_DEBNCE 0x64 /* Card detect debounce */
+#define MSHCI_USRID 0x68 /* User ID */
+#define MSHCI_VERID 0x6C /* Version ID */
+#define MSHCI_HCON 0x70 /* Hardware Configuration */
+#define MSHCI_UHS_REG 0x74 /* UHS and DDR setting */
+#define MSHCI_BMOD 0x80 /* Bus mode register */
+#define MSHCI_PLDMND 0x84 /* Poll demand */
+#define MSHCI_DBADDR 0x88 /* Descriptor list base address */
+#define MSHCI_IDSTS 0x8C /* Internal DMAC status */
+#define MSHCI_IDINTEN 0x90 /* Internal DMAC interrupt enable */
+#define MSHCI_DSCADDR 0x94 /* Current host descriptor address */
+#define MSHCI_BUFADDR 0x98 /* Current host buffer address */
+#define MSHCI_CLKSEL 0x9C /* Drv/sample clock selection register */
+#define MSHCI_WAKEUPCON 0xA0 /* Wakeup control register */
+#define MSHCI_CLOCKCON 0xA4 /* Clock (delay) control register */
+#define MSHCI_FIFO 0x200
+#define MSHCI_FIFODAT(x) (x) /* FIFO data read write */
+
+
+/*****************************************************
+ * Control Register Register
+ * MSHCI_CTRL - offset 0x00
+ *****************************************************/
+
+#define CTRL_RESET (0x1<<0) /* Reset DWC_mobile_storage controller */
+#define FIFO_RESET (0x1<<1) /* Reset FIFO */
+#define DMA_RESET (0x1<<2) /* Reset DMA interface */
+#define INT_ENABLE (0x1<<4) /* Global interrupt enable/disable bit */
+#define DMA_ENABLE (0x1<<5) /* DMA transfer mode enable/disable bit */
+#define READ_WAIT (0x1<<6) /* For sending read-wait to SDIO cards */
+#define SEND_IRQ_RESP (0x1<<7) /* Send auto IRQ response */
+#define ABRT_READ_DATA (0x1<<8)
+#define SEND_CCSD (0x1<<9)
+#define SEND_AS_CCSD (0x1<<10)
+#define CEATA_INTSTAT (0x1<<11)
+#define CARD_VOLA (0xF<<16)
+#define CARD_VOLB (0xF<<20)
+#define ENABLE_OD_PULLUP (0x1<<24)
+#define ENABLE_IDMAC (0x1<<25)
+#define MSHCI_RESET_ALL (0x1)
+
+/*****************************************************
+ * Power Enable Register
+ * MSHCI_PWREN - offset 0x04
+ *****************************************************/
+#define POWER_ENABLE (0x1<<0)
+
+/*****************************************************
+* Clock Enable Register
+* MSHCI_CLKENA - offset 0x10
+*****************************************************/
+#define CLK_SDMMC_MAX (48000000) /* 96Mhz. it SHOULDBE optimized */
+#define CLK_ENABLE (0x1<<0)
+#define CLK_DISABLE (0x0<<0)
+
+
+/*****************************************************
+ * Interrupt Mask Register
+ * MSHCI_INTMSK - offset 0x24
+ *****************************************************/
+#define INT_MASK (0xFFFF<<0)
+#define SDIO_INT_MASK (0xFFFF<<16)
+#define SDIO_INT_ENABLE (0x1<<16)
+
+/* interrupt bits */
+#define INTMSK_ALL 0xFFFFFFFF
+#define INTMSK_CDETECT (0x1<<0)
+#define INTMSK_RE (0x1<<1)
+#define INTMSK_CDONE (0x1<<2)
+#define INTMSK_DTO (0x1<<3)
+#define INTMSK_TXDR (0x1<<4)
+#define INTMSK_RXDR (0x1<<5)
+#define INTMSK_RCRC (0x1<<6)
+#define INTMSK_DCRC (0x1<<7)
+#define INTMSK_RTO (0x1<<8)
+#define INTMSK_DRTO (0x1<<9)
+#define INTMSK_HTO (0x1<<10)
+#define INTMSK_FRUN (0x1<<11)
+#define INTMSK_HLE (0x1<<12)
+#define INTMSK_SBE (0x1<<13)
+#define INTMSK_ACD (0x1<<14)
+#define INTMSK_EBE (0x1<<15)
+#define INTMSK_DMA (INTMSK_ACD|INTMSK_RXDR|INTMSK_TXDR)
+
+#define INT_SRC_IDMAC (0x0)
+#define INT_SRC_MINT (0x1)
+
+
+/*****************************************************
+ * Command Register
+ * MSHCI_CMD - offset 0x2C
+ *****************************************************/
+
+#define CMD_RESP_EXP_BIT (0x1<<6)
+#define CMD_RESP_LENGTH_BIT (0x1<<7)
+#define CMD_CHECK_CRC_BIT (0x1<<8)
+#define CMD_DATA_EXP_BIT (0x1<<9)
+#define CMD_RW_BIT (0x1<<10)
+#define CMD_TRANSMODE_BIT (0x1<<11)
+#define CMD_SENT_AUTO_STOP_BIT (0x1<<12)
+#define CMD_WAIT_PRV_DAT_BIT (0x1<<13)
+#define CMD_ABRT_CMD_BIT (0x1<<14)
+#define CMD_SEND_INIT_BIT (0x1<<15)
+#define CMD_CARD_NUM_BITS (0x1F<<16)
+#define CMD_SEND_CLK_ONLY (0x1<<21)
+#define CMD_READ_CEATA (0x1<<22)
+#define CMD_CCS_EXPECTED (0x1<<23)
+#define CMD_USE_HOLD_REG (0x1<<29)
+#define CMD_STRT_BIT (0x1<<31)
+#define CMD_ONLY_CLK (CMD_STRT_BIT | CMD_SEND_CLK_ONLY | \
+ CMD_WAIT_PRV_DAT_BIT)
+
+/*****************************************************
+ * Raw Interrupt Register
+ * MSHCI_RINTSTS - offset 0x44
+ *****************************************************/
+#define INT_STATUS (0xFFFF<<0)
+#define SDIO_INTR (0xFFFF<<16)
+#define DATA_ERR (INTMSK_EBE|INTMSK_SBE|INTMSK_HLE|INTMSK_FRUN |\
+ INTMSK_EBE |INTMSK_DCRC)
+#define DATA_TOUT (INTMSK_HTO|INTMSK_DRTO)
+#define DATA_STATUS (DATA_ERR|DATA_TOUT|INTMSK_RXDR|INTMSK_TXDR|INTMSK_DTO)
+#define CMD_STATUS (INTMSK_RTO|INTMSK_RCRC|INTMSK_CDONE|INTMSK_RE)
+#define CMD_ERROR (INTMSK_RCRC|INTMSK_RTO|INTMSK_RE)
+
+
+/*****************************************************
+ * Status Register
+ * MSHCI_STATUS - offset 0x48
+ *****************************************************/
+#define FIFO_RXWTRMARK (0x1<<0)
+#define FIFO_TXWTRMARK (0x1<<1)
+#define FIFO_EMPTY (0x1<<2)
+#define FIFO_FULL (0x1<<3)
+#define CMD_FSMSTAT (0xF<<4)
+#define DATA_3STATUS (0x1<<8)
+#define DATA_BUSY (0x1<<9)
+#define DATA_MCBUSY (0x1<<10)
+#define RSP_INDEX (0x3F<<11)
+#define FIFO_COUNT (0x1FFF<<17)
+#define DMA_ACK (0x1<<30)
+#define DMA_REQ (0x1<<31)
+#define FIFO_WIDTH (0x4)
+#define FIFO_DEPTH (0x20)
+#define FIFO_SIZE (0x80)
+#define GET_FIFO_COUNT(x) (((x)&0x3ffe0000)>>17)
+
+
+
+/*****************************************************
+ * FIFO Threshold Watermark Register
+ * MSHCI_FIFOTH - offset 0x4C
+ *****************************************************/
+#define TX_WMARK (0xFFF<<0)
+#define RX_WMARK (0xFFF<<16)
+#define MSIZE_MASK (0x7<<28)
+
+/* DW DMA Mutiple Transaction Size */
+#define MSIZE_1 (0<<28)
+#define MSIZE_4 (1<<28)
+#define MSIZE_8 (2<<28)
+#define MSIZE_16 (3<<28)
+#define MSIZE_32 (4<<28)
+#define MSIZE_64 (5<<28)
+#define MSIZE_128 (6<<28)
+#define MSIZE_256 (7<<28)
+
+#define TX_WMARK_DEFAULT (0x10<<0)
+#define RX_WMARK_DEFAULT (0x10<<16)
+
+//#define TX_WMARK_DEFAULT (0x40<<0)
+//#define RX_WMARK_DEFAULT (0x3F<<16)
+
+
+/*****************************************************
+ * Bus Mode Register
+ * MSHCI_UHS_REG - offset 0x74
+ *****************************************************/
+#define UHS_DDR (0x1<<16)
+#define UHS_NON_DDR (0x0<<16)
+#define BUSMODE_DDR 1
+#define BUSMODE_NON_DDR 0
+
+/*****************************************************
+ * Bus Mode Register
+ * MSHCI_BMOD - offset 0x80
+ *****************************************************/
+#define BMOD_IDMAC_RESET (0x1<<0)
+#define BMOD_IDMAC_FB (0x1<<1)
+#define BMOD_IDMAC_ENABLE (0x1<<7)
+
+/*****************************************************
+ * Hardware Configuration Register
+ * MSHCI_IDSTS - offset 0x8c
+ *****************************************************/
+#define IDSTS_FSM (0xf<<13)
+#define IDSTS_EB (0x7<<10)
+#define IDSTS_AIS (0x1<<9)
+#define IDSTS_NIS (0x1<<8)
+#define IDSTS_CES (0x1<<5)
+#define IDSTS_DU (0x1<<4)
+#define IDSTS_FBE (0x1<<2)
+#define IDSTS_RI (0x1<<1)
+#define IDSTS_TI (0x1<<0)
+
+
+/*****************************************************
+ * Card Type Register
+ * MSHCI_CTYPE - offset 0x18
+ *****************************************************/
+#define CARD_WIDTH14 (0xFFFF<<0)
+#define CARD_WIDTH8 (0xFFFF<<16)
+
+struct mshci_idmac {
+ UINT32 des0;
+ UINT32 des1;
+ UINT32 des2;
+ UINT32 des3;
+#define MSHCI_IDMAC_OWN (1<<31)
+#define MSHCI_IDMAC_ER (1<<5)
+#define MSHCI_IDMAC_CH (1<<4)
+#define MSHCI_IDMAC_FS (1<<3)
+#define MSHCI_IDMAC_LD (1<<2)
+#define MSHCI_IDMAC_DIC (1<<1)
+#define INTMSK_IDMAC_ALL (0x337)
+#define INTMSK_IDMAC_ERROR (0x214)
+};
+
+typedef enum {
+ READ,
+ WRITE
+} OPERATION_TYPE;
+
+
+/*****************************************************
+ * DMA Buffer structure
+ *
+ * CH0 for eMMC 0x40300000--0x40380000
+ * CH2 for SD Card 0x40380000--0x40400000
+
+
+ *****************************************************/
+#define EMMC_DMA_PHYSICAL_BUFFER_BASE 0x40300000
+#define EMMC_DMA_PHYSICAL_BUFFER_SIZE 0x00100000 //1MB
+#define PHY_BUF_OFFSET 0x1000 //4K
+#define PHY_BUF_SIZE 0x1000 //4K
+
+#define MAX_MSHC_TRANSFER_SIZE 0x40000 //512blocks, 256KB
+
+
+
+/*****************************************************
+ * External Functions
+ *****************************************************/
+
+
+EFI_STATUS InitializeMSHC (VOID);
+VOID UpdateMSHCClkFrequency (UINTN NewCLK);
+void MSHC_reset_fifo(void);
+extern void MSHC_reset_all(void);
+extern VOID PrepareTransfer (IN OUT VOID *Buffer, UINTN ByteCount, IN OPERATION_TYPE OperationType);
+extern EFI_STATUS MSHC_ReadFIFO(IN UINTN Size32, OUT VOID *Buffer);
+extern EFI_STATUS MSHC_WriteFIFO(IN UINTN Size32, IN VOID *Buffer);
+void mshci_set_mdma_desc(UINT8 *desc_vir, UINT8 *desc_phy,
+ UINT32 des0, UINT32 des1, UINT32 des2);
+EFI_STATUS MSHC_ReadDMA(OUT VOID *Buffer, IN UINTN BlockCount);
+EFI_STATUS MSHC_WriteDMA(IN VOID *Buffer, IN UINTN BlockCount);
+
+
+
+#endif
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_CMD.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_CMD.h
new file mode 100755
index 000000000..615da0799
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe_CMD.h
@@ -0,0 +1,165 @@
+/** @file
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 _MSHCDXE_CMD_H_
+#define _MSHCDXE_CMD_H_
+
+
+
+#define HosttoCard 0x1
+#define CardtoHost 0x0
+
+#define ENDMA BIT0
+#define ENBLKCNT BIT1
+#define RD1WT0 BIT4
+#define MUL1SIN0 BIT5
+#define RSPTYP136 (0x1 << 16)
+#define RSPTYP48 (0x2 << 16)
+#define RSPTYP48B (0x3 << 16)
+#define ENCMDCRC BIT19
+#define ENCMDIDX BIT20
+#define DATAPRNT BIT21
+
+
+#define CMDCOMP BIT0
+#define TRNSCOMP BIT1
+#define RDYFORWT BIT4
+#define RDYFORRD BIT5
+#define CARDINSERT BIT6
+#define CARDREMOVE BIT7
+#define ERRINT BIT15
+#define CMDTOUTERR BIT16
+#define CMDCRCERR BIT17
+#define CMDEBITERR BIT18
+#define CMDIDXERR BIT19
+#define DATATOUTERR BIT20
+#define DATACRCERR BIT21
+#define DATAEBITERR BIT22
+
+
+
+
+/* Command Definitions */
+#define INDX(CMD_INDX) (CMD_INDX & 0x3F)
+
+#define CMD0 INDX(0)
+#define CMD0_INT_EN (CMDCOMP | CMDEBITERR)
+
+#define CMD1 (INDX(1) | RSPTYP48)
+#define CMD1_INT_EN (CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD2 (INDX(2) | ENCMDCRC | RSPTYP136)
+#define CMD2_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD3 (INDX(3) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD3_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD5 (INDX(5) | RSPTYP48)
+#define CMD5_INT_EN (CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD7 (INDX(7) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD7_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD8 (INDX(8) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD8_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+//Reserved(0)[12:31], Supply voltage(1)[11:8], check pattern(0xCE)[7:0] = 0x1CE
+#define CMD8_ARG (0x0UL << 12 | BIT8 | 0xCEUL << 0)
+
+#define CMD9 (INDX(9) | ENCMDCRC | RSPTYP136)
+#define CMD9_INT_EN (CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD13 (INDX(13) | RSPTYP48)
+#define CMD13_INT_EN (CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+
+//#define CMD16 (INDX(16) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD16 (INDX(16) | ENCMDIDX | RSPTYP48)
+#define CMD16_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD17 (INDX(17) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48 | RD1WT0)
+#define CMD17_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | TRNSCOMP | RDYFORRD | CMDTOUTERR | DATATOUTERR | DATACRCERR | DATAEBITERR | CMDEBITERR)
+
+//#define CMD18 (INDX(18) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48 | MUL1SIN0 | RD1WT0 | ENBLKCNT | ENDMA)
+#define CMD18 (INDX(18) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48 )
+#define CMD18_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | TRNSCOMP | RDYFORRD | CMDTOUTERR | DATATOUTERR | DATACRCERR | DATAEBITERR | CMDEBITERR)
+
+#define CMD23 (INDX(23) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD23_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD24 (INDX(24) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD24_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | TRNSCOMP | RDYFORWT | CMDTOUTERR | DATATOUTERR | DATACRCERR | DATAEBITERR | CMDEBITERR)
+
+//#define CMD25 (INDX(25) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48 | MUL1SIN0 | ENBLKCNT | ENDMA)
+#define CMD25 (INDX(25) | DATAPRNT | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD25_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | TRNSCOMP | RDYFORWT | CMDTOUTERR | DATATOUTERR | DATACRCERR | DATAEBITERR | CMDEBITERR)
+
+#define CMD35 (INDX(35) | ENCMDCRC | RSPTYP48)
+#define CMD36 (INDX(36) | ENCMDCRC | RSPTYP48)
+#define CMD38 (INDX(38) |RSPTYP48)
+
+#define CMD55 (INDX(55) | ENCMDIDX | ENCMDCRC | RSPTYP48)
+#define CMD55_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define ACMD41 (INDX(41) | RSPTYP48)
+#define ACMD41_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define ACMD6 (INDX(6) | RSPTYP48)
+#define ACMD6_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+#define CMD62 (INDX(62) | RSPTYP48)
+#define CMD62_INT_EN (CMDIDXERR | CMDCRCERR | CMDCOMP | CMDEBITERR | CMDTOUTERR)
+
+
+
+/*
+EFI_STATUS
+EFI_SUCCESS 0
+
+EFI_LOAD_ERROR 1
+EFI_INVALID_PARAMETER 2
+EFI_UNSUPPORTED 3
+EFI_BAD_BUFFER_SIZE 4
+EFI_BUFFER_TOO_SMALL 5
+EFI_NOT_READY 6
+EFI_DEVICE_ERROR 7
+EFI_WRITE_PROTECTED 8
+EFI_OUT_OF_RESOURCES 9
+EFI_VOLUME_CORRUPTED 10
+EFI_VOLUME_FULL 11
+EFI_NO_MEDIA 12
+EFI_MEDIA_CHANGED 13
+EFI_NOT_FOUND 14
+EFI_ACCESS_DENIED 15
+EFI_NO_RESPONSE 16
+EFI_NO_MAPPING 17
+EFI_TIMEOUT 18
+EFI_NOT_STARTED 19
+EFI_ALREADY_STARTED 20
+EFI_ABORTED 21
+EFI_ICMO_ERROR 22
+EFI_TFTP_ERROR 23
+EFI_PROTOCOL_ERROR 24
+EFI_INCOMPATIBLE_VERSION 25
+EFI_SECURITY_VIOLATION 26
+EFI_CRC_ERROR 27
+EFI_END_OF_MEDIA 28
+EFI_END_OF_FILE 31
+EFI_INVALID_LANGUAGE 32
+EFI_COMPROMISED_DATA 33
+
+
+*/
+
+#endif
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMC_Fvb.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMC_Fvb.c
new file mode 100755
index 000000000..ee8d1c902
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMC_Fvb.c
@@ -0,0 +1,587 @@
+/** @file
+ eMMC firmware volume block protocol driver
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UncachedMemoryAllocationLib.h>
+
+#include <Protocol/FirmwareVolumeBlock.h>
+#include "eMMCDxe.h"
+
+
+//#undef EFI_D_INFO
+//#define EFI_D_INFO 1
+
+
+EFI_FVB_ATTRIBUTES_2 gAttribute = (EFI_FVB2_READ_STATUS|EFI_FVB2_WRITE_STATUS|EFI_FVB2_ALIGNMENT_32);
+UINT32 *FVBMemAddr;
+
+/**
+ The GetAttributes() function retrieves the attributes and
+ current settings of the block.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the
+ attributes and current settings are
+ returned. Type EFI_FVB_ATTRIBUTES_2 is defined
+ in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were
+ returned.
+
+**/
+
+EFI_STATUS
+EFIAPI
+FvbGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ *Attributes = gAttribute;
+ DEBUG ((EFI_D_INFO, "FvbGetAttributes 0x%x\n", gAttribute));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The SetAttributes() function sets configurable firmware volume
+ attributes and returns the new settings of the firmware volume.
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes On input, Attributes is a pointer to
+ EFI_FVB_ATTRIBUTES_2 that contains the
+ desired firmware volume settings. On
+ successful return, it contains the new
+ settings of the firmware volume. Type
+ EFI_FVB_ATTRIBUTES_2 is defined in
+ EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ @retval EFI_INVALID_PARAMETER The attributes requested are in
+ conflict with the capabilities
+ as declared in the firmware
+ volume header.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ gAttribute |= *Attributes;
+ *Attributes = gAttribute;
+ DEBUG ((EFI_D_INFO, "FvbSetAttributes 0x%x\n", gAttribute));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The GetPhysicalAddress() function retrieves the base address of
+ a memory-mapped firmware volume. This function should be called
+ only for memory-mapped firmware volumes.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Address Pointer to a caller-allocated
+ EFI_PHYSICAL_ADDRESS that, on successful
+ return from GetPhysicalAddress(), contains the
+ base address of the firmware volume.
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ UINT32 NVBase = PcdGet32(PcdFlashNvStorageVariableBase);
+ UINT32 NVSize = PcdGet32(PcdFlashNvStorageVariableSize);
+
+ DEBUG ((EFI_D_INFO, "FvbGetPhysicalAddress Base:0x%x, Size:0x%x\n", NVBase, NVSize));
+
+ if(FVBMemAddr==NULL)
+ {
+ FVBMemAddr = (UINT32 *)UncachedAllocatePool(NVSize);
+ DEBUG ((EFI_D_INFO, "FvbGetPhysicalAddress MEM Alloc 0x%x\n", FVBMemAddr));
+
+ if(FVBMemAddr==NULL)
+ {
+ DEBUG ((EFI_D_ERROR, "FvbGetPhysicalAddress Alloc failed \n"));
+ return EFI_UNSUPPORTED;
+ }
+ }
+ else
+ {
+ DEBUG ((EFI_D_INFO, "FvbGetPhysicalAddress already Allocated 0x%x \n", FVBMemAddr));
+ }
+
+ CopyMem((VOID *)FVBMemAddr, (VOID *)NVBase, NVSize);
+ Address = (EFI_PHYSICAL_ADDRESS *)FVBMemAddr;
+ DEBUG ((EFI_D_INFO, "FvbGetPhysicalAddress Addr:0x%x\n", Address));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The GetBlockSize() function retrieves the size of the requested
+ block. It also returns the number of additional blocks with
+ the identical size. The GetBlockSize() function is used to
+ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba Indicates the block for which to return the size.
+
+ @param BlockSize Pointer to a caller-allocated UINTN in which
+ the size of the block is returned.
+
+ @param NumberOfBlocks Pointer to a caller-allocated UINTN in
+ which the number of consecutive blocks,
+ starting with Lba, is returned. All
+ blocks in this range have a size of
+ BlockSize.
+
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ *BlockSize = gSDMMCMedia.BlockSize;
+ *NumberOfBlocks = 512;
+ DEBUG ((EFI_D_INFO, "FvbGetBlockSize numblocks:%d\n", *NumberOfBlocks));
+ return status;
+}
+
+
+
+/**
+ Reads the specified number of bytes into a buffer from the specified block.
+
+ The Read() function reads the requested number of bytes from the
+ requested block and stores them in the provided buffer.
+ Implementations should be mindful that the firmware volume
+ might be in the ReadDisabled state. If it is in this state,
+ the Read() function must return the status code
+ EFI_ACCESS_DENIED without modifying the contents of the
+ buffer. The Read() function must also prevent spanning block
+ boundaries. If a read is requested that would span a block
+ boundary, the read must read up to the boundary but not
+ beyond. The output parameter NumBytes must be set to correctly
+ indicate the number of bytes actually read. The caller must be
+ aware that a read may be partially completed.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index
+ from which to read.
+
+ @param Offset Offset into the block at which to begin reading.
+
+ @param NumBytes Pointer to a UINTN. At entry, *NumBytes
+ contains the total size of the buffer. At
+ exit, *NumBytes contains the total number of
+ bytes read.
+
+ @param Buffer Pointer to a caller-allocated buffer that will
+ be used to hold the data that is read.
+
+ @retval EFI_SUCCESS The firmware volume was read successfully,
+ and contents are in Buffer.
+
+ @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA
+ boundary. On output, NumBytes
+ contains the total number of bytes
+ returned in Buffer.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the
+ ReadDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not
+ functioning correctly and could
+ not be read.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ )
+{
+ EFI_BLOCK_IO_PROTOCOL *EFIBlockIO = (EFI_BLOCK_IO_PROTOCOL *)This;
+ EFI_STATUS status = EFI_SUCCESS;
+ VOID *TempBuf = NULL;
+ UINT32 NumBlock;
+ UINT32 AllocSize=0;
+ Lba += MSHC_BOOT_SECURE_OFFSET;
+
+ DEBUG ((EFI_D_INFO, "FvbRead Offset : %d, Numbytes : %d\n", Offset, *NumBytes));
+
+ if(gCardInit==TRUE)
+ {
+ if (0 == (*NumBytes%gSDMMCMedia.BlockSize))
+ {
+ NumBlock = (*NumBytes/gSDMMCMedia.BlockSize);
+ }
+ else
+ {
+ NumBlock = (*NumBytes/gSDMMCMedia.BlockSize) + 1;
+ }
+ //DEBUG ((EFI_D_INFO, "FvbRead numblock : %d, BlockSize : %d\n", NumBlock, gSDMMCMedia.BlockSize));
+
+ AllocSize = NumBlock*gSDMMCMedia.BlockSize;
+ TempBuf = AllocatePool(AllocSize);
+ //ZeroMem (TempBuf, NumBlock*gSDMMCMedia.BlockSize);
+ if(TempBuf==NULL)
+ {
+ DEBUG ((EFI_D_ERROR, "FvbRead AllocatePool Failed!!\n"));
+ status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ status = SdReadWrite(EFIBlockIO, Lba, TempBuf, AllocSize, READ);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((EFI_D_ERROR, "FvbRead Failed 0x%x\n", status));
+ status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+
+ CopyMem((VOID *)Buffer, (VOID *)(TempBuf+Offset), *NumBytes);
+ }
+
+ Exit:
+
+ if (TempBuf != NULL)
+ {
+ FreePool(TempBuf);
+ }
+
+ return status;
+}
+
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ The Write() function writes the specified number of bytes from
+ the provided buffer to the specified block and offset. If the
+ firmware volume is sticky write, the caller must ensure that
+ all the bits of the specified range to write are in the
+ EFI_FVB_ERASE_POLARITY state before calling the Write()
+ function, or else the result will be unpredictable. This
+ unpredictability arises because, for a sticky-write firmware
+ volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
+ state but cannot flip it back again. Before calling the
+ Write() function, it is recommended for the caller to first call
+ the EraseBlocks() function to erase the specified block to
+ write. A block erase cycle will transition bits from the
+ (NOT)EFI_FVB_ERASE_POLARITY state back to the
+ EFI_FVB_ERASE_POLARITY state. Implementations should be
+ mindful that the firmware volume might be in the WriteDisabled
+ state. If it is in this state, the Write() function must
+ return the status code EFI_ACCESS_DENIED without modifying the
+ contents of the firmware volume. The Write() function must
+ also prevent spanning block boundaries. If a write is
+ requested that spans a block boundary, the write must store up
+ to the boundary but not beyond. The output parameter NumBytes
+ must be set to correctly indicate the number of bytes actually
+ written. The caller must be aware that a write may be
+ partially completed. All writes, partial or otherwise, must be
+ fully flushed to the hardware before the Write() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index to write to.
+
+ @param Offset Offset into the block at which to begin writing.
+
+ @param NumBytes The pointer to a UINTN. At entry, *NumBytes
+ contains the total size of the buffer. At
+ exit, *NumBytes contains the total number of
+ bytes actually written.
+
+ @param Buffer The pointer to a caller-allocated buffer that
+ contains the source for the write.
+
+ @retval EFI_SUCCESS The firmware volume was written successfully.
+
+ @retval EFI_BAD_BUFFER_SIZE The write was attempted across an
+ LBA boundary. On output, NumBytes
+ contains the total number of bytes
+ actually written.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the
+ WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is malfunctioning
+ and could not be written.
+
+
+**/
+EFI_STATUS
+EFIAPI
+FvbWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_BLOCK_IO_PROTOCOL *EFIBlockIO = (EFI_BLOCK_IO_PROTOCOL *)This;
+ EFI_STATUS status = EFI_SUCCESS;
+ VOID *TempBuf = NULL;
+ UINT32 NumBlock;
+ UINT32 AllocSize=0;
+ Lba += MSHC_BOOT_SECURE_OFFSET;
+
+ DEBUG ((EFI_D_INFO, "FvbWrite Offset : %d, Numbyte : %d\n", Offset, *NumBytes));
+
+ if(gCardInit==TRUE)
+ {
+ if (0 == (*NumBytes%gSDMMCMedia.BlockSize))
+ {
+ NumBlock = (*NumBytes/gSDMMCMedia.BlockSize);
+ }
+ else
+ {
+ NumBlock = (*NumBytes/gSDMMCMedia.BlockSize) + 1;
+ }
+ //DEBUG ((EFI_D_INFO, "FvbWrite numblock : %d, BlockSize : %d\n", NumBlock, gSDMMCMedia.BlockSize));
+
+ AllocSize = (NumBlock*gSDMMCMedia.BlockSize);
+ TempBuf = AllocatePool(AllocSize);
+ //ZeroMem (TempBuf, NumBlock*gSDMMCMedia.BlockSize);
+ if(TempBuf==NULL)
+ {
+ DEBUG ((EFI_D_ERROR, "FvbWrite AllocatePool Failed!!\n"));
+ status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ status = SdReadWrite(EFIBlockIO, Lba, TempBuf, AllocSize, READ);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((EFI_D_ERROR, "FvbWrite Read Failed 0x%x\n", status));
+ status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+
+ CopyMem((VOID *)(TempBuf+Offset), (VOID *)Buffer, *NumBytes);
+
+ status = SdReadWrite(EFIBlockIO, Lba, TempBuf, AllocSize, WRITE);
+ if(status!=EFI_SUCCESS)
+ {
+ DEBUG ((EFI_D_ERROR, "FvbWrite Write Failed 0x%x\n", status));
+ status = EFI_ACCESS_DENIED;
+ goto Exit;
+ }
+ }
+ else
+ {
+ DEBUG ((EFI_D_ERROR, "FvbWrite Error eMMC is not ready\n"));
+ }
+
+ Exit:
+
+ if (TempBuf != NULL)
+ {
+ FreePool(TempBuf);
+ }
+
+ return status;
+}
+
+
+/**
+ Erases and initializes a firmware volume block.
+
+ The EraseBlocks() function erases one or more blocks as denoted
+ by the variable argument list. The entire parameter list of
+ blocks must be verified before erasing any blocks. If a block is
+ requested that does not exist within the associated firmware
+ volume (it has a larger index than the last block of the
+ firmware volume), the EraseBlocks() function must return the
+ status code EFI_INVALID_PARAMETER without modifying the contents
+ of the firmware volume. Implementations should be mindful that
+ the firmware volume might be in the WriteDisabled state. If it
+ is in this state, the EraseBlocks() function must return the
+ status code EFI_ACCESS_DENIED without modifying the contents of
+ the firmware volume. All calls to EraseBlocks() must be fully
+ flushed to the hardware before the EraseBlocks() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+
+ @param ... The variable argument list is a list of tuples.
+ Each tuple describes a range of LBAs to erase
+ and consists of the following:
+ - An EFI_LBA that indicates the starting LBA
+ - A UINTN that indicates the number of blocks to
+ erase.
+
+ The list is terminated with an
+ EFI_LBA_LIST_TERMINATOR. For example, the
+ following indicates that two ranges of blocks
+ (5-7 and 10-11) are to be erased: EraseBlocks
+ (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
+
+ @retval EFI_SUCCESS The erase request successfully
+ completed.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the
+ WriteDisabled state.
+ @retval EFI_DEVICE_ERROR The block device is not functioning
+ correctly and could not be written.
+ The firmware device may have been
+ partially erased.
+ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed
+ in the variable argument list do
+ not exist in the firmware volume.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ )
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ UINTN StartBlock, NumBlock;
+ UINTN Index;
+ VA_LIST Marker;
+
+ VA_START (Marker, This);
+
+ for (Index = 0, status = EFI_SUCCESS; !EFI_ERROR (status); Index++)
+ {
+ StartBlock = VA_ARG (Marker, UINTN);
+ NumBlock = VA_ARG (Marker, UINTN);
+ DEBUG ((EFI_D_INFO, "FvbEraseBlocks start:%d numblock:%d\n", StartBlock, NumBlock));
+
+ if(StartBlock==0xFFFFFFFF)
+ {
+ break;
+ }
+
+ StartBlock += MSHC_BOOT_SECURE_OFFSET;
+ /* MMC High Capacity erase minimum size is 512KB */
+ status = EraseBlockData(MSHC_BOOT_PARTITION, StartBlock, NumBlock);
+ }
+
+ VA_END (Marker);
+ return status;
+}
+
+
+//
+// Making this global saves a few bytes in image size
+//
+EFI_HANDLE gFvbHandle = NULL;
+
+
+///
+/// The Firmware Volume Block Protocol is the low-level interface
+/// to a firmware volume. File-level access to a firmware volume
+/// should not be done using the Firmware Volume Block Protocol.
+/// Normal access to a firmware volume must use the Firmware
+/// Volume Protocol. Typically, only the file system driver that
+/// produces the Firmware Volume Protocol will bind to the
+/// Firmware Volume Block Protocol.
+///
+EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL gFvbProtocol = {
+ FvbGetAttributes,
+ FvbSetAttributes,
+ FvbGetPhysicalAddress,
+ FvbGetBlockSize,
+ FvbRead,
+ FvbWrite,
+ FvbEraseBlocks,
+ ///
+ /// The handle of the parent firmware volume.
+ ///
+ NULL
+};
+
+
+#if 0
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+FvbDxeInitialize ()
+{
+ EFI_STATUS Status;
+
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gFvbHandle,
+ &gEfiFirmwareVolumeBlockProtocolGuid, &gFvbProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ // SetVertAddressEvent ()
+
+ // GCD Map NAND as RT
+
+ return Status;
+}
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec b/SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
new file mode 100755
index 000000000..d4863ced4
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
@@ -0,0 +1,101 @@
+#/** @file
+# Arm RealView EB package.
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+#
+# 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]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = ExynosPkg
+ PACKAGE_GUID = ec1a4982-4a00-47e7-8df5-69c8ce895427
+ PACKAGE_VERSION = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+# Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+ Include # Root include for the package
+
+[Guids.common]
+ gExynosPkgTokenSpaceGuid = { 0x70b6655a, 0x7a03, 0x11e0, { 0xbe, 0x19, 0x00, 0x26, 0xb9, 0x73, 0x3e, 0x2c} }
+
+[PcdsFeatureFlag.common]
+
+[PcdsFixedAtBuild.common]
+
+ #
+ # Samsung
+ #
+ # Framebuffer Base Address and size
+ gExynosPkgTokenSpaceGuid.PcdFrameBufferBase|0|UINT32|0x4E000000
+ gExynosPkgTokenSpaceGuid.PcdFrameBufferSize|0|UINT32|0x00400000
+
+ # Memory Partition : Shared memory 1MB (0x4000_0000 -- 0x4010_0000)
+ gExynosPkgTokenSpaceGuid.PcdSmemBaseAddress|0|UINT32|0x40000000
+ gExynosPkgTokenSpaceGuid.PcdSmemSize|0|UINT32|0x00100000
+
+ # Memory Partition : EMMC DMA buffer Address and Size 1MB (0x4030_0000 -- 0x4040_0000)
+ gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferBase|0|UINT32|0x40300000
+# gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferSize|0|UINT32|0x00100000
+
+ ## iRam Base Address and size.
+ gExynosPkgTokenSpaceGuid.PcdiRamBootBase|0|UINT32|0x00020000
+ gExynosPkgTokenSpaceGuid.PcdiRamBootSize|0|UINT32|0x00020001
+
+ gExynosPkgTokenSpaceGuid.PcdiRamStackBase|0|UINT32|0x00020002
+ gExynosPkgTokenSpaceGuid.PcdiRamStackSize|0|UINT32|0x00020003
+
+ gExynosPkgTokenSpaceGuid.PcdMpSharedArgsBase|0x8ff00000|UINT32|0x00000020
+ gExynosPkgTokenSpaceGuid.PcdMpSharedArgsSize|0x00100000|UINT32|0x00000021
+
+ gExynosPkgTokenSpaceGuid.PcdPeiServicePtrAddr|0|UINT32|0x00000003
+ gExynosPkgTokenSpaceGuid.PcdConsoleUartBase|0|UINT32|0x00000004
+ gExynosPkgTokenSpaceGuid.PcdWinDebugUartBase|0|UINT32|0x00000005
+ gExynosPkgTokenSpaceGuid.PcdCmuBase|0|UINT32|0x00000006
+ gExynosPkgTokenSpaceGuid.PcdPWMTimerBase|0|UINT32|0x00000007
+ gExynosPkgTokenSpaceGuid.PcdPmuBase|0|UINT32|0x00000008
+ gExynosPkgTokenSpaceGuid.PcdGdbUartBase|0|UINT32|0x00000009
+ gExynosPkgTokenSpaceGuid.PcdGpioPart1Base|0|UINT32|0x0000000A
+ gExynosPkgTokenSpaceGuid.PcdGpioPart2Base|0|UINT32|0x0000000B
+ gExynosPkgTokenSpaceGuid.PcdGpioPart3Base|0|UINT32|0x0000000C
+ gExynosPkgTokenSpaceGuid.PcdGpioPart4Base|0|UINT32|0x0000000D
+ gExynosPkgTokenSpaceGuid.PcdSdMmcBase|0|UINT32|0x0000000E
+ gExynosPkgTokenSpaceGuid.PcdSysBase|0|UINT32|0x0000000F
+ gExynosPkgTokenSpaceGuid.PcdFIMD1Base|0|UINT32|0x00000010
+ gExynosPkgTokenSpaceGuid.PcdGICBase|0|UINT32|0x00000011
+ gExynosPkgTokenSpaceGuid.PcdTZPCBase|0|UINT32|0x00000012
+ gExynosPkgTokenSpaceGuid.PcdDSIM1Base|0|UINT32|0x00000013
+ gExynosPkgTokenSpaceGuid.PcdSMC911XBase|0|UINT32|0x00000014
+ gExynosPkgTokenSpaceGuid.PcdRtcBase|0|UINT32|0x00000015
+ gExynosPkgTokenSpaceGuid.PcdExynos5250Evt1|FALSE|BOOLEAN|0x00000016
+ gExynosPkgTokenSpaceGuid.PcdSdMmcCH0Base|0|UINT32|0x00000017
+ gExynosPkgTokenSpaceGuid.PcdCryptoBase|0|UINT32|0x00000018
+
+
+ #
+ # SMBIOS related
+ #
+ gExynosPkgTokenSpaceGuid.PcdProcessorInfoSockInfoStr|"Samsung Exynos5250"|VOID*|0x00000A00
+ # Following can be changed by OEM's as it suits their products
+ gExynosPkgTokenSpaceGuid.PcdSystemMfrStr|"Samsung's OEM"|VOID*|0x00000A01
+ gExynosPkgTokenSpaceGuid.PcdSystemProductNameStr|"Exynos5250 Product"|VOID*|0x00000A02
+ gExynosPkgTokenSpaceGuid.PcdSystemProductFamilyStr|"Exynos5250 Product Family"|VOID*|0x00000A03
+
+
+# Samsung specific GUID = be26dd4f-9d02-413c-aa4f-dcd4aa334122
+[Protocols.common]
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/ExynosLib.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/ExynosLib.h
new file mode 100644
index 000000000..8cd9fad2e
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/ExynosLib.h
@@ -0,0 +1,42 @@
+/** @file
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 __EXYNOSLIB_H__
+#define __EXYNOSLIB_H__
+
+/*===========================================================================
+ MACRO DECLARATIONS
+===========================================================================*/
+/**
+ gExynosPkgTokenSpaceGuid GUID definition.
+*/
+#define EXYNOSPKG_TOKEN_SPACE_GUID \
+ { 0x70b6655a, 0x7a03, 0x11e0, { 0xbe, 0x19, 0x00, 0x26, 0xb9, 0x73, 0x3e, 0x2c } }
+
+/*===========================================================================
+ EXTERNAL VARIABLES
+===========================================================================*/
+/**
+ External reference to the gExynosPkgTokenSpaceGuid GUID.
+*/
+extern EFI_GUID gExynosPkgTokenSpaceGuid;
+
+
+UINT32
+EFIAPI
+GpioBase (
+ IN UINTN Port
+ );
+
+#endif // __EXYNOSLIB_H__
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/ExynosTimerLib.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/ExynosTimerLib.h
new file mode 100644
index 000000000..783dd6d5f
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/ExynosTimerLib.h
@@ -0,0 +1,56 @@
+/** @file
+*
+* Copyright (c) 2012, Samsung Electronics Co. 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 _EXYNOSTIMERLIB_H__
+#define _EXYNOSTIMERLIB_H__
+
+#define PWM_TCFG0_OFFSET (0x0000)
+#define PWM_TCFG1_OFFSET (0x0004)
+#define PWM_TCON_OFFSET (0x0008)
+#define PWM_TCNTB0_OFFSET (0x000C)
+#define PWM_TCMPB0_OFFSET (0x0010)
+#define PWM_TCNTO0_OFFSET (0x0014)
+#define PWM_TCNTB1_OFFSET (0x0018)
+#define PWM_TCMPB1_OFFSET (0x001C)
+#define PWM_TCNTO1_OFFSET (0x0020)
+#define PWM_TCNTB2_OFFSET (0x0024)
+#define PWM_TCMPB2_OFFSET (0x0028)
+#define PWM_TCNTO2_OFFSET (0x002C)
+#define PWM_TCNTB3_OFFSET (0x0030)
+#define PWM_TCMPB3_OFFSET (0x0034)
+#define PWM_TCNTO3_OFFSET (0x0038)
+#define PWM_TINT_CSTAT_OFFSET (0x0044)
+
+// Exynos4210 Timer constants
+#define Exynos4210_TIMER_LOAD_REG 0x00
+#define Exynos4210_TIMER_CURRENT_REG 0x04
+#define Exynos4210_TIMER_CONTROL_REG 0x08
+#define Exynos4210_TIMER_INT_CLR_REG 0x0C
+#define Exynos4210_TIMER_RAW_INT_STS_REG 0x10
+#define Exynos4210_TIMER_MSK_INT_STS_REG 0x14
+#define Exynos4210_TIMER_BG_LOAD_REG 0x18
+
+// Timer control register bit definitions
+#define Exynos4210_TIMER_CTRL_ONESHOT BIT0
+#define Exynos4210_TIMER_CTRL_32BIT BIT1
+#define Exynos4210_TIMER_CTRL_PRESCALE_MASK (BIT3|BIT2)
+#define Exynos4210_PRESCALE_DIV_1 0
+#define Exynos4210_PRESCALE_DIV_16 BIT2
+#define Exynos4210_PRESCALE_DIV_256 BIT3
+#define Exynos4210_TIMER_CTRL_INT_ENABLE BIT5
+#define Exynos4210_TIMER_CTRL_PERIODIC BIT6
+#define Exynos4210_TIMER_CTRL_ENABLE BIT7
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/MpParkLib.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/MpParkLib.h
new file mode 100644
index 000000000..688051b42
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/MpParkLib.h
@@ -0,0 +1,51 @@
+/** @file
+ Template for Timer Architecture Protocol driver of the ARM flavor
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 __MPPARKLIB_H_
+#define __MPPARKLIB_H_
+
+/*===========================================================================
+
+ INCLUDE FILES FOR MODULE
+
+===========================================================================*/
+
+/*===========================================================================
+
+ Defines and Structs
+
+===========================================================================*/
+extern UINT32 MpParkGPT0CntAddr;
+extern UINT32 MpParkGPT0MatchAddr;
+extern UINT32 MpParkGPT0EnableAddr;
+extern UINT32 MpParkMPMCountAddr;
+
+/*===========================================================================
+
+ Public Functions
+
+===========================================================================*/
+void CPU1_Start(void);
+
+
+/*===========================================================================
+
+ Private Functions
+
+===========================================================================*/
+
+#endif // __MPPARKLIB_H_
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/com_dtypes.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/com_dtypes.h
new file mode 100644
index 000000000..02e113c31
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Library/com_dtypes.h
@@ -0,0 +1,186 @@
+#ifndef COM_DTYPES_H
+#define COM_DTYPES_H
+/** @file
+ Template for Timer Architecture Protocol driver of the ARM flavor
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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.
+
+**/
+
+
+/*===========================================================================
+
+ Data Declarations
+
+===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For NT apps we want to use the Win32 definitions and/or those
+** supplied by the Win32 compiler for things like NULL, MAX, MIN
+** abs, labs, etc.
+*/
+#ifdef T_WINNT
+ #ifndef WIN32
+ #define WIN32
+ #endif
+ #include <stdlib.h>
+#endif
+
+/* ------------------------------------------------------------------------
+** Constants
+** ------------------------------------------------------------------------ */
+
+#ifdef TRUE
+#undef TRUE
+#endif
+
+#ifdef FALSE
+#undef FALSE
+#endif
+
+#define TRUE 1 /* Boolean true value. */
+#define FALSE 0 /* Boolean false value. */
+
+#define ON 1 /* On value. */
+#define OFF 0 /* Off value. */
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+/* -----------------------------------------------------------------------
+** Standard Types
+** ----------------------------------------------------------------------- */
+
+/* The following definitions are the same accross platforms. This first
+** group are the sanctioned types.
+*/
+#ifndef _ARM_ASM_
+#ifndef _BOOLEAN_DEFINED
+typedef unsigned char boolean; /* Boolean value type. */
+#define _BOOLEAN_DEFINED
+#endif
+
+
+#if defined(DALSTDDEF_H) /* guards against a known re-definer */
+#define _BOOLEAN_DEFINED
+#define _UINT32_DEFINED
+#define _UINT16_DEFINED
+#define _UINT8_DEFINED
+#define _INT32_DEFINED
+#define _INT16_DEFINED
+#define _INT8_DEFINED
+#define _UINT64_DEFINED
+#define _INT64_DEFINED
+#define _BYTE_DEFINED
+#endif /* #if !defined(DALSTDDEF_H) */
+
+#ifndef _UINT32_DEFINED
+typedef unsigned long int uint32; /* Unsigned 32 bit value */
+#define _UINT32_DEFINED
+#endif
+
+#ifndef _UINT16_DEFINED
+typedef unsigned short uint16; /* Unsigned 16 bit value */
+#define _UINT16_DEFINED
+#endif
+
+#ifndef _UINT8_DEFINED
+typedef unsigned char uint8; /* Unsigned 8 bit value */
+#define _UINT8_DEFINED
+#endif
+
+#ifndef _INT32_DEFINED
+typedef signed long int int32; /* Signed 32 bit value */
+#define _INT32_DEFINED
+#endif
+
+#ifndef _INT16_DEFINED
+typedef signed short int16; /* Signed 16 bit value */
+#define _INT16_DEFINED
+#endif
+
+#ifndef _INT8_DEFINED
+typedef signed char int8; /* Signed 8 bit value */
+#define _INT8_DEFINED
+#endif
+
+/* This group are the deprecated types. Their use should be
+** discontinued and new code should use the types above
+*/
+#ifndef _BYTE_DEFINED
+typedef unsigned char byte; /* Unsigned 8 bit value type. */
+#define _BYTE_DEFINED
+#endif
+
+typedef unsigned short word; /* Unsinged 16 bit value type. */
+typedef unsigned long dword; /* Unsigned 32 bit value type. */
+
+typedef unsigned char uint1; /* Unsigned 8 bit value type. */
+typedef unsigned short uint2; /* Unsigned 16 bit value type. */
+typedef unsigned long uint4; /* Unsigned 32 bit value type. */
+
+typedef signed char int1; /* Signed 8 bit value type. */
+typedef signed short int2; /* Signed 16 bit value type. */
+typedef long int int4; /* Signed 32 bit value type. */
+
+typedef signed long sint31; /* Signed 32 bit value */
+typedef signed short sint15; /* Signed 16 bit value */
+typedef signed char sint7; /* Signed 8 bit value */
+
+typedef uint16 UWord16 ;
+typedef uint32 UWord32 ;
+typedef int32 Word32 ;
+typedef int16 Word16 ;
+typedef uint8 UWord8 ;
+typedef int8 Word8 ;
+typedef int32 Vect32 ;
+
+#if (! defined T_WINNT) && (! defined __GNUC__)
+ /* Non WinNT Targets */
+ #ifndef _INT64_DEFINED
+ typedef long long int64; /* Signed 64 bit value */
+ #define _INT64_DEFINED
+ #endif
+ #ifndef _UINT64_DEFINED
+ typedef unsigned long long uint64; /* Unsigned 64 bit value */
+ #define _UINT64_DEFINED
+ #endif
+#else /* T_WINNT || TARGET_OS_SOLARIS || __GNUC__ */
+ /* WINNT or SOLARIS based targets */
+ #if (defined __GNUC__)
+ #ifndef _INT64_DEFINED
+ typedef long long int64;
+ #define _INT64_DEFINED
+ #endif
+ #ifndef _UINT64_DEFINED
+ typedef unsigned long long uint64;
+ #define _UINT64_DEFINED
+ #endif
+ #else
+ typedef __int64 int64; /* Signed 64 bit value */
+ #ifndef _UINT64_DEFINED
+ typedef unsigned __int64 uint64; /* Unsigned 64 bit value */
+ #define _UINT64_DEFINED
+ #endif
+ #endif
+#endif /* T_WINNT */
+
+#endif /* _ARM_ASM_ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* COM_DTYPES_H */
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/ArmPlatform.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/ArmPlatform.h
new file mode 100755
index 000000000..4d5f7d86f
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/ArmPlatform.h
@@ -0,0 +1,692 @@
+/** @file
+* Header defining RealView EB constants (Base addresses, sizes, flags)
+*
+* Copyright (c) 2012, Samsung Electronics Co. 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 __ARMPLATFORM_H__
+#define __ARMPLATFORM_H__
+
+/*******************************************
+// Platform Memory Map
+*******************************************/
+
+/*******************************************
+// Motherboard peripherals
+*******************************************/
+//PMU DOMAIN offsets
+#define SWRESET_OFFSET (0x400)
+#define PMU_DISP1_CONFIGURATION_OFFSET (0x40A0)
+#define PMU_DISP1_STATUS_OFFSET (0x40A4)
+
+#define LOCAL_PWR_ENABLE (0x07)
+
+#define PMU_MIPI_PHY1_CONTROL_OFFSET (0x0714)
+
+// SYSTRCL Register
+#define ARM_EB_SYSCTRL 0x10001000
+
+#define PL011_CONSOLE_UART_SPEED 115200
+
+// IRAM & RAM Base Address
+#define CONFIG_PHY_SDRAM_BASE (0x40000000)
+#define CONFIG_PHY_IRAM_BASE (0x02020000)
+#define CONFIG_PHY_UEFI_BASE (CONFIG_PHY_SDRAM_BASE)
+#define CONFIG_SECURE_CONTEXT_BASE (CONFIG_PHY_IRAM_BASE + 0x4c00)
+#define CONFIG_PHY_TZSW_BASE (CONFIG_PHY_IRAM_BASE + 0x8000)
+#define CONFIG_PHY_IRAM_NS_BASE (CONFIG_PHY_IRAM_BASE + 0x2F000)
+#define CONFIG_IMAGE_INFO_BASE (CONFIG_PHY_IRAM_NS_BASE + 0x11000)
+
+// Exynos5250 DMC Base Address : Not used it.
+#define Exynos5250_DMC_DELAY 0x3000
+#define Exynos5250_DMC_0_BASE 0x10C00000
+#define Exynos5250_DMC_1_BASE 0x10C10000
+
+
+// Exynos5250 DMC Base Address
+#define DMC_CTRL_BASE 0x10DD0000
+
+#define DMC_CONCONTROL 0x00
+#define DMC_MEMCONTROL 0x04
+#define DMC_MEMCONFIG0 0x08
+#define DMC_MEMCONFIG1 0x0C
+#define DMC_DIRECTCMD 0x10
+#define DMC_PRECHCONFIG 0x14
+#define DMC_PHYCONTROL0 0x18
+#define DMC_PWRDNCONFIG 0x28
+#define DMC_TIMINGPZQ 0x2C
+#define DMC_TIMINGAREF 0x30
+#define DMC_TIMINGROW 0x34
+#define DMC_TIMINGDATA 0x38
+#define DMC_TIMINGPOWER 0x3C
+#define DMC_PHYSTATUS 0x40
+#define DMC_CHIPSTATUS_CH0 0x48
+#define DMC_CHIPSTATUS_CH1 0x4C
+#define DMC_MRSTATUS 0x54
+#define DMC_QOSCONTROL0 0x60
+#define DMC_QOSCONTROL1 0x68
+#define DMC_QOSCONTROL2 0x70
+#define DMC_QOSCONTROL3 0x78
+#define DMC_QOSCONTROL4 0x80
+#define DMC_QOSCONTROL5 0x88
+#define DMC_QOSCONTROL6 0x90
+#define DMC_QOSCONTROL7 0x98
+#define DMC_QOSCONTROL8 0xA0
+#define DMC_QOSCONTROL9 0xA8
+#define DMC_QOSCONTROL10 0xB0
+#define DMC_QOSCONTROL11 0xB8
+#define DMC_QOSCONTROL12 0xC0
+#define DMC_QOSCONTROL13 0xC8
+#define DMC_QOSCONTROL14 0xD0
+#define DMC_QOSCONTROL15 0xD8
+#define DMC_IVCONTROL 0xF0
+#define DMC_WRTRA_CONFIG 0x00F4
+#define DMC_RDLVL_CONFIG 0x00F8
+#define DMC_BRBRSVCONTROL 0x0100
+#define DMC_BRBRSVCONFIG 0x0104
+#define DMC_BRBQOSCONFIG 0x0108
+#define DMC_MEMBASECONFIG0 0x010C
+#define DMC_MEMBASECONFIG1 0x0110
+#define DMC_WRLVL_CONFIG 0x0120
+#define DMC_PMNC_PPC 0xE000
+#define DMC_CNTENS_PPC 0xE010
+#define DMC_CNTENC_PPC 0xE020
+#define DMC_INTENS_PPC 0xE030
+#define DMC_INTENC_PPC 0xE040
+#define DMC_FLAG_PPC 0xE050
+#define DMC_CCNT_PPC 0xE100
+#define DMC_PMCNT0_PPC 0xE110
+#define DMC_PMCNT1_PPC 0xE120
+#define DMC_PMCNT2_PPC 0xE130
+#define DMC_PMCNT3_PPC 0xE140
+
+/* PHY Control Register */
+#define PHY0_CTRL_BASE 0x10C00000
+#define PHY1_CTRL_BASE 0x10C10000
+
+#define DMC_PHY_CON0 0x00
+#define DMC_PHY_CON1 0x04
+#define DMC_PHY_CON2 0x08
+#define DMC_PHY_CON3 0x0C
+#define DMC_PHY_CON4 0x10
+#define DMC_PHY_CON6 0x18
+#define DMC_PHY_CON8 0x20
+#define DMC_PHY_CON10 0x28
+#define DMC_PHY_CON11 0x2C
+#define DMC_PHY_CON12 0x30
+#define DMC_PHY_CON13 0x34
+#define DMC_PHY_CON14 0x38
+#define DMC_PHY_CON15 0x3C
+#define DMC_PHY_CON16 0x40
+#define DMC_PHY_CON17 0x48
+#define DMC_PHY_CON18 0x4C
+#define DMC_PHY_CON19 0x50
+#define DMC_PHY_CON20 0x54
+#define DMC_PHY_CON21 0x58
+#define DMC_PHY_CON22 0x5C
+#define DMC_PHY_CON23 0x60
+#define DMC_PHY_CON24 0x64
+#define DMC_PHY_CON25 0x68
+#define DMC_PHY_CON26 0x6C
+#define DMC_PHY_CON27 0x70
+#define DMC_PHY_CON28 0x74
+#define DMC_PHY_CON29 0x78
+#define DMC_PHY_CON30 0x7C
+#define DMC_PHY_CON31 0x80
+#define DMC_PHY_CON32 0x84
+#define DMC_PHY_CON33 0x88
+#define DMC_PHY_CON34 0x8C
+#define DMC_PHY_CON35 0x90
+#define DMC_PHY_CON36 0x94
+#define DMC_PHY_CON37 0x98
+#define DMC_PHY_CON38 0x9C
+#define DMC_PHY_CON39 0xA0
+#define DMC_PHY_CON40 0xA4
+#define DMC_PHY_CON41 0xA8
+#define DMC_PHY_CON42 0xAC
+
+
+
+
+
+
+// Exynos5250 UART Register
+#define Exynos5250_UART_BASE 0x12C10000
+
+#define ULCON_OFFSET 0x00
+#define UCON_OFFSET 0x04
+#define UFCON_OFFSET 0x08
+#define UMCON_OFFSET 0x0C
+#define UTRSTAT_OFFSET 0x10
+#define UERSTAT_OFFSET 0x14
+#define UFSTAT_OFFSET 0x18
+#define UMSTAT_OFFSET 0x1C
+#define UTXH_OFFSET 0x20
+#define URXH_OFFSET 0x24
+#define UBRDIV_OFFSET 0x28
+#define UDIVSLOT_OFFSET 0x2C
+#define UINTP_OFFSET 0x30
+#define UINTSP_OFFSET 0x34
+#define UINTM_OFFSET 0x38
+
+
+#define UARTLCR_H ULCON_OFFSET
+#define UARTECR UFCON_OFFSET
+#define UARTCR UCON_OFFSET
+#define UARTIBRD UBRDIV_OFFSET
+#define UARTFBRD UDIVSLOT_OFFSET
+
+#define UART_TX_EMPTY_FLAG_MASK (0x02)
+#define UART_RX_EMPTY_FLAG_MASK (0x01)
+// Exynos5250 TZPC Register
+#define Exynos5250_TZPC0_BASE 0x10100000
+#define Exynos5250_TZPC1_BASE 0x10110000
+#define Exynos5250_TZPC2_BASE 0x10120000
+#define Exynos5250_TZPC3_BASE 0x10130000
+#define Exynos5250_TZPC4_BASE 0x10140000
+#define Exynos5250_TZPC5_BASE 0x10150000
+#define Exynos5250_TZPC6_BASE 0x10160000
+#define Exynos5250_TZPC7_BASE 0x10170000
+#define Exynos5250_TZPC8_BASE 0x10180000
+#define Exynos5250_TZPC9_BASE 0x10190000
+
+
+#define TZPC0_OFFSET 0x00000
+#define TZPC1_OFFSET 0x10000
+#define TZPC2_OFFSET 0x20000
+#define TZPC3_OFFSET 0x30000
+#define TZPC4_OFFSET 0x40000
+#define TZPC5_OFFSET 0x50000
+#define TZPC6_OFFSET 0x60000
+#define TZPC7_OFFSET 0x70000
+#define TZPC8_OFFSET 0x80000
+#define TZPC9_OFFSET 0x90000
+
+#define TZPC_DECPROT0SET_OFFSET 0x804
+#define TZPC_DECPROT1SET_OFFSET 0x810
+#define TZPC_DECPROT2SET_OFFSET 0x81C
+#define TZPC_DECPROT3SET_OFFSET 0x828
+
+
+// Exynos5250 CMU Base Address
+#define Exynos5250_CMU_DELAY 0x2000
+#define Exynos5250_CMU_BASE 0x10010000
+#define Exynos5250_CMU_DIV_DMC0 0x10500
+
+#define APLL_AFC_ENB 0x1
+#define APLL_AFC 0xC
+
+/* MPLL_CON1 */
+#define MPLL_AFC_ENB 0x0
+#if defined(CONFIG_CLK_800_330_165) || defined(CONFIG_CLK_1000_330_165)
+#define MPLL_AFC 0xD
+#elif defined(CONFIG_CLK_1000_400_200) || defined(CONFIG_CLK_1000_200_200) || defined(CONFIG_CLK_800_400_200)
+#define MPLL_AFC 0x1C
+#endif
+
+#define EPLL_PDIV 0x3
+#define EPLL_K 0x0
+#define VPLL_PDIV 0x3
+#define VPLL_SDIV 0x2
+
+#define VPLL_SSCG_EN 0x0
+#define VPLL_SEL_PF 0x0
+#define VPLL_MRR 0x11
+#define VPLL_MFR 0x0
+#define VPLL_K 0x400
+/********************************************************/
+
+/* Set PLL */
+#define set_pll(mdiv, pdiv, sdiv) (1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
+
+/* CLK_SRC_CPU */
+/* 0 = MOUTAPLL, 1 = SCLKMPLL */
+#define MUX_HPM_SEL_MOUTAPLL 0
+#define MUX_HPM_SEL_SCLKMPLL 1
+#define MUX_CORE_SEL_MOUTAPLL 0
+#define MUX_CORE_SEL_SCLKMPLL 1
+
+/* 0 = FILPLL, 1 = MOUT */
+#define MUX_MPLL_SEL_FILPLL 0
+#define MUX_MPLL_SEL_MOUTMPLLFOUT 1
+
+#define MUX_APLL_SEL_FILPLL 0
+#define MUX_APLL_SEL_MOUTMPLLFOUT 1
+
+#define CLK_SRC_CPU_VAL_FINPLL ((MUX_HPM_SEL_MOUTAPLL << 20) \
+ | (MUX_CORE_SEL_MOUTAPLL <<16) \
+ | (MUX_MPLL_SEL_FILPLL << 8) \
+ | (MUX_APLL_SEL_FILPLL <<0))
+
+#define CLK_SRC_CPU_VAL_MOUTMPLLFOUT ((MUX_HPM_SEL_MOUTAPLL << 20) \
+ | (MUX_CORE_SEL_MOUTAPLL <<16) \
+ | (MUX_MPLL_SEL_MOUTMPLLFOUT << 8) \
+ | (MUX_APLL_SEL_MOUTMPLLFOUT <<0))
+
+/* CLK_DIV_CPU0 */
+#define APLL_RATIO 0x1
+#define PCLK_DBG_RATIO 0x1
+#define ATB_RATIO 0x3
+#define COREM1_RATIO 0x7
+#define COREM0_RATIO 0x3
+#define CORE_RATIO 0x0
+
+/* CLK_DIV_CPU1 */
+#define HPM_RATIO 0x0
+#define COPY_RATIO 0x3
+#define CLK_DIV_CPU1_VAL ((HPM_RATIO << 4) | (COPY_RATIO))
+
+/* CLK_SRC_DMC */
+#define MUX_PWI_SEL 0x0
+#define MUX_CORE_TIMERS_SEL 0x0
+#define MUX_DPHY_SEL 0x0
+#define MUX_DMC_BUS_SEL 0x0
+#define CLK_SRC_DMC_VAL ((MUX_PWI_SEL << 16) \
+ | (MUX_CORE_TIMERS_SEL << 12) \
+ | (MUX_DPHY_SEL << 8) \
+ | (MUX_DMC_BUS_SEL << 4))
+
+/* CLK_DIV_DMC0 */
+#if defined(CONFIG_CLK_1000_200_200)
+#define CORE_TIMERS_RATIO 0x1
+#define COPY2_RATIO 0x3
+#define DMCP_RATIO 0x1
+#define DMCD_RATIO 0x0
+#define DMC_RATIO 0x3
+#define DPHY_RATIO 0x1
+#define ACP_PCLK_RATIO 0x1
+#define ACP_RATIO 0x3
+#else
+#define CORE_TIMERS_RATIO 0x1
+#define COPY2_RATIO 0x3
+#define DMCP_RATIO 0x1
+#define DMCD_RATIO 0x1
+#define DMC_RATIO 0x1
+#define DPHY_RATIO 0x1
+#define ACP_PCLK_RATIO 0x1
+#endif
+#define CLK_DIV_DMC0_VAL ((CORE_TIMERS_RATIO << 28) \
+ | (COPY2_RATIO << 24) \
+ | (DMCP_RATIO << 20) \
+ | (DMCD_RATIO << 16) \
+ | (DMC_RATIO << 12) \
+ | (DPHY_RATIO << 8) \
+ | (ACP_PCLK_RATIO << 4) \
+ | (ACP_RATIO))
+
+/* CLK_DIV_DMC1 */
+#define DPM_RATIO 0x1
+#define DVSEM_RATIO 0x1
+#define PWI_RATIO 0x1
+#define CLK_DIV_DMC1_VAL ((DPM_RATIO << 24) \
+ | (DVSEM_RATIO << 16) \
+ | (PWI_RATIO << 8))
+
+/* CLK_SRC_TOP0 */
+#define MUX_ONENAND_SEL 0x0 /* 0 = DOUT133, 1 = DOUT166 */
+#define MUX_ACLK_133_SEL 0x0 /* 0 = SCLKMPLL, 1 = SCLKAPLL */
+#define MUX_ACLK_160_SEL 0x0
+#define MUX_ACLK_100_SEL 0x0
+#define MUX_ACLK_200_SEL 0x0
+#define MUX_VPLL_SEL 0x0
+#define MUX_EPLL_SEL 0x0
+
+/* CLK_SRC_TOP1 */
+#define VPLLSRC_SEL 0x0 /* 0 = FINPLL, 1 = SCLKHDMI27M */
+
+/* CLK_DIV_TOP */
+#define ONENAND_RATIO 0x0
+#define ACLK_160_RATIO 0x4
+#define ACLK_100_RATIO 0x7
+#define ACLK_200_RATIO 0x3
+#define CLK_DIV_TOP_VAL ((ONENAND_RATIO << 16) \
+ | (ACLK_133_RATIO << 12) \
+ | (ACLK_160_RATIO << 8) \
+ | (ACLK_100_RATIO << 4) \
+ | (ACLK_200_RATIO))
+
+/* CLK_SRC_LEFTBUS */
+#define MUX_GDL_SEL 0x0
+#define CLK_SRC_LEFTBUS_VAL (MUX_GDL_SEL)
+
+/* CLK_DIV_LEFRBUS */
+#define GPL_RATIO 0x1
+#define GDL_RATIO 0x3
+#define CLK_DIV_LEFRBUS_VAL ((GPL_RATIO << 4) \
+ | (GDL_RATIO))
+
+/* CLK_SRC_RIGHTBUS */
+#define MUX_GDR_SEL 0x0
+#define CLK_SRC_RIGHTBUS_VAL (MUX_GDR_SEL)
+
+/* CLK_DIV_RIGHTBUS */
+#define GPR_RATIO 0x1
+#define GDR_RATIO 0x3
+#define CLK_DIV_RIGHTBUS_VAL ((GPR_RATIO << 4) \
+ | (GDR_RATIO))
+
+#define PLL_LOCKTIME 0x1C20
+
+/* CLK_SRC_PERIL0 */
+#define PWM_SEL 0
+#define UART5_SEL 6
+#define UART4_SEL 6
+#define UART3_SEL 6
+#define UART2_SEL 6
+#define UART1_SEL 6
+#define UART0_SEL 6
+#define CLK_SRC_PERIL0_VAL ((PWM_SEL << 24)\
+ | (UART5_SEL << 20) \
+ | (UART4_SEL << 16) \
+ | (UART3_SEL << 12) \
+ | (UART2_SEL<< 8) \
+ | (UART1_SEL << 4) \
+ | (UART0_SEL))
+
+/* CLK_DIV_PERIL0 */
+#if defined(CONFIG_CLK_800_330_165) || defined(CONFIG_CLK_1000_330_165)
+#define UART5_RATIO 7
+#define UART4_RATIO 7
+#define UART3_RATIO 7
+#define UART2_RATIO 7
+#define UART1_RATIO 7
+#define UART0_RATIO 7
+#elif defined(CONFIG_CLK_1000_400_200) || defined(CONFIG_CLK_1000_200_200) || defined(CONFIG_CLK_800_400_200)
+#define UART5_RATIO 8
+#define UART4_RATIO 8
+#define UART3_RATIO 8
+#define UART2_RATIO 8
+#define UART1_RATIO 8
+#define UART0_RATIO 8
+#endif
+#define CLK_DIV_PERIL0_VAL ((UART5_RATIO << 20) \
+ | (UART4_RATIO << 16) \
+ | (UART3_RATIO << 12) \
+ | (UART2_RATIO << 8) \
+ | (UART1_RATIO << 4) \
+ | (UART0_RATIO))
+
+#define MPLL_DEC (MPLL_MDIV * MPLL_MDIV / (MPLL_PDIV * 2^(MPLL_SDIV-1)))
+
+#if defined(CONFIG_CLK_800_330_165) || defined(CONFIG_CLK_1000_330_165)
+#define UART_UBRDIV_VAL 0x2B/* (SCLK_UART/(115200*16) -1) */
+#define UART_UDIVSLOT_VAL 0xC /*((((SCLK_UART*10/(115200*16) -10))%10)*16/10)*/
+#elif defined(CONFIG_CLK_1000_400_200) || defined(CONFIG_CLK_1000_200_200) || defined(CONFIG_CLK_800_400_200)
+#define UART_UBRDIV_VAL 0x2F /* (SCLK_UART/(115200*16) -1) */
+#define UART_UDIVSLOT_VAL 0x3 /*((((SCLK_UART*10/(115200*16) -10))%10)*16/10)*/
+#endif
+
+#define UART_115200_IDIV UART_UBRDIV_VAL
+#define UART_115200_FDIV UART_UDIVSLOT_VAL
+
+#define UART_38400_IDIV UART_UBRDIV_VAL
+#define UART_38400_FDIV UART_UDIVSLOT_VAL
+
+#define UART_19200_IDIV UART_UBRDIV_VAL
+#define UART_19200_FDIV UART_UDIVSLOT_VAL
+
+#define UART_LCON_VAL 0x03
+#define UART_ECR_VAL 0x111
+#define UART_CR_VAL 0x3C5
+
+// System Configuration Controller register Base addresses
+#define SYS_DISP1BLK_CFG_OFFSET (0x0214)
+#define FIMDBYPASS_DISP1 (0x01 << 15)
+
+//FIMD register offsets
+#define VIDCON0_OFFSET (0x00)
+#define VIDCON1_OFFSET (0x20004)/* Video control 1 */
+#define VIDCON2_OFFSET (0x0008) /* Video control 2 */
+#define VIDTCON0_OFFSET (0x20010) /* Video time control 0 */
+#define VIDTCON1_OFFSET (0x20014) /* Video time control 1 */
+#define VIDTCON2_OFFSET (0x20018) /* Video time control 2 */
+#define SHADOWCON_OFFSET (0x0034) /* Window Shadow control */
+#define WINCON_OFFSET(x) (0x0020 + (x * 0x04))
+#define VIDOSD_A_OFFSET(x) (0x0040 + (x * 0x10))
+#define VIDOSD_B_OFFSET(x) (0x0044 + (x * 0x10))
+#define VIDOSD_C_OFFSET(x) (0x0048 + (x * 0x10))
+#define VIDADDR_START0_OFFSET(x)(0x00A0 + (x * 0x08))
+#define VIDADDR_END0_OFFSET(x) (0x00D0 + (x * 0x08))
+#define VIDADDR_SIZE_OFFSET(x) (0x0100 + (x * 0x04))
+
+// MIPI-DSIM register offsets
+#define DSIM_STATUS (0x00)
+#define DSIM_SWRST (0x04)
+#define DSIM_CLKCTRL (0x08)
+#define DSIM_TIMEOUT (0x0C)
+#define DSIM_CONFIG (0x10)
+#define DSIM_ESCMODE (0x14)
+#define DSIM_MDRESOL (0x18)
+#define DSIM_MVPORCH (0x1C)
+#define DSIM_MHPORCH (0x20)
+#define DSIM_MSYNC (0x24)
+#define DSIM_SDRESOL (0x28)
+#define DSIM_INTSRC (0x2C)
+#define DSIM_INTMSK (0x30)
+#define DSIM_PKTHDR (0x34)
+#define DSIM_PAYLOAD (0x38)
+#define DSIM_RXFIFO (0x3C)
+#define DSIM_FIFOTHLD (0x40)
+#define DSIM_FIFOCTRL (0x44)
+#define DSIM_MEMACCHR (0x48)
+#define DSIM_PLLCTRL (0x4C)
+#define DSIM_PLLTMR (0x50)
+#define DSIM_PHYACCHR (0x54)
+#define DSIM_PHYACCHR1 (0x58)
+
+// RTC register offset
+#define EXYNOS_RTCREG(x) (x)
+#define EXYNOS_INTP EXYNOS_RTCREG(0x30)
+#define EXYNOS_INTP_ALM (1 << 1)
+#define EXYNOS_INTP_TIC (1 << 0)
+
+#define EXYNOS_RTCCON EXYNOS_RTCREG(0x40)
+#define EXYNOS_RTCCON_RTCEN (1<<0)
+#define EXYNOS_RTCCON_CLKSEL (1<<1)
+#define EXYNOS_RTCCON_CNTSEL (1<<2)
+#define EXYNOS_RTCCON_CLKRST (1<<3)
+#define EXYNOS_RTCCON_TICEN (1<<8)
+
+#define EXYNOS_RTCCON_TICMSK (0xF<<7)
+#define EXYNOS_RTCCON_TICSHT (7)
+
+#define EXYNOS_TICNT EXYNOS_RTCREG(0x44)
+#define EXYNOS_TICNT_ENABLE (1<<7)
+
+#define EXYNOS_RTCALM EXYNOS_RTCREG(0x50)
+#define EXYNOS_RTCALM_ALMEN (1<<6)
+#define EXYNOS_RTCALM_YEAREN (1<<5)
+#define EXYNOS_RTCALM_MONEN (1<<4)
+#define EXYNOS_RTCALM_DAYEN (1<<3)
+#define EXYNOS_RTCALM_HOUREN (1<<2)
+#define EXYNOS_RTCALM_MINEN (1<<1)
+#define EXYNOS_RTCALM_SECEN (1<<0)
+
+#define EXYNOS_RTCALM_ALL \
+ EXYNOS_RTCALM_ALMEN | EXYNOS_RTCALM_YEAREN | EXYNOS_RTCALM_MONEN |\
+ EXYNOS_RTCALM_DAYEN | EXYNOS_RTCALM_HOUREN | EXYNOS_RTCALM_MINEN |\
+ EXYNOS_RTCALM_SECEN
+
+
+#define EXYNOS_ALMSEC EXYNOS_RTCREG(0x54)
+#define EXYNOS_ALMMIN EXYNOS_RTCREG(0x58)
+#define EXYNOS_ALMHOUR EXYNOS_RTCREG(0x5c)
+
+#define EXYNOS_ALMDAY EXYNOS_RTCREG(0x60)
+#define EXYNOS_ALMMON EXYNOS_RTCREG(0x64)
+#define EXYNOS_ALMYEAR EXYNOS_RTCREG(0x68)
+
+//#define EXYNOS_RTCRST EXYNOS_RTCREG(0x6c)
+
+#define EXYNOS_BCDSEC EXYNOS_RTCREG(0x70)
+#define EXYNOS_BCDMIN EXYNOS_RTCREG(0x74)
+#define EXYNOS_BCDHOUR EXYNOS_RTCREG(0x78)
+#define EXYNOS_BCDDAY EXYNOS_RTCREG(0x7c)
+#define EXYNOS_BCDDAYWEEK EXYNOS_RTCREG(0x80)
+#define EXYNOS_BCDMON EXYNOS_RTCREG(0x84)
+#define EXYNOS_BCDYEAR EXYNOS_RTCREG(0x88)
+
+// Kimoon add RTC clock gate
+#define CLK_GATE_IP_PERIR (0xC960)
+#define CLK_RTC_OFFSET (0x1 << 15)
+#define CLK_RTC_MASK (0x0 << 15)
+#define CLK_RTC_UNMASK (0x1 << 15)
+
+//#define CLK_DIV_FSYS2 (CLK_BASE + 0xC548)
+//#define CLK_DIV_FSYS3 (CLK_BASE + 0xC54C)
+
+
+/*******************************************
+* Interrupt Map
+*******************************************/
+
+// Timer Interrupts
+#define Exynos5250_INT_NUM(x) ((x) + 32)
+
+#define PWM_TIMER0_INTERRUPT_NUM Exynos5250_INT_NUM(36)
+#define PWM_TIMER1_INTERRUPT_NUM Exynos5250_INT_NUM(37)
+#define PWM_TIMER2_INTERRUPT_NUM Exynos5250_INT_NUM(38)
+#define PWM_TIMER3_INTERRUPT_NUM Exynos5250_INT_NUM(39)
+#define PWM_TIMER4_INTERRUPT_NUM Exynos5250_INT_NUM(40)
+
+/*******************************************
+* EFI Memory Map in Permanent Memory (DRAM)
+*******************************************/
+
+//gpio definitions as required by the Embedded gpio module
+#define DISTANCE_BTWN_PORTS (0x20)
+
+#define GPIO_CON (0x00)
+#define GPIO_DATAIN (0x04)
+#define GPIO_PUD (0x08)
+#define GPIO_DRV (0x0C)
+
+#define GPIO_DATAIN_MASK(x) (1UL << (x))
+#define GPIO_PUD_MASK(x) (3UL << (x*2))
+#define GPIO_DRV_MASK(x) (3UL << (x*2))
+#define GPIO_SFN_MASK(x) (15UL <<(x*4))
+
+#define GPIO_SFN_EN(x) (2UL << (x*4))
+#define GPIO_OP_EN(x) (1UL << (x*4))
+
+#define GPIO_PUD_DIS(x) (0UL << (x*2))
+#define GPIO_PDN_EN(x) (1UL << (x*2))
+#define GPIO_PUP_EN(x) (3UL << (x*2))
+#define GPIO_DATA_HIGH(x) (1UL << (x))
+#define GPIO_DATA_LOW(x) (0UL << (x))
+
+#define GPIO_DRV_SET(strength,pin) (strength << (pin*2))
+
+#define PIN0 (0x00)
+#define PIN1 (0x01)
+#define PIN2 (0x02)
+#define PIN3 (0x03)
+#define PIN4 (0x04)
+#define PIN5 (0x05)
+#define PIN6 (0x06)
+#define PIN7 (0x07)
+
+// 0x1140_0000
+#define GPA0 (0x00)
+#define GPA1 (0x01)
+#define GPA2 (0x02)
+#define GPB0 (0x03)
+#define GPB1 (0x04)
+#define GPB2 (0x05)
+#define GPB3 (0x06)
+#define GPC0 (0x07)
+#define GPC1 (0x08)
+#define GPC2 (0x09)
+#define GPC3 (0x0A)
+#define GPD0 (0x0B)
+#define GPD1 (0x0C)
+#define GPY0 (0x0D)
+#define GPY1 (0x0E)
+#define GPY2 (0x0F)
+#define GPY3 (0x10)
+#define GPY4 (0x11)
+#define GPY5 (0x12)
+#define GPY6 (0x13)
+#define GPX0 (0x60)
+#define GPX1 (0x61)
+#define GPX2 (0x62)
+#define GPX3 (0x63)
+
+// 0x1340_0000
+#define GPE0 (0x70)
+#define GPE1 (0x71)
+#define GPF0 (0x72)
+#define GPF1 (0x73)
+#define GPG0 (0x74)
+#define GPG1 (0x75)
+#define GPG2 (0x76)
+#define GPH0 (0x77)
+#define GPH1 (0x78)
+
+// 0x10D1_0000
+#define GPV0 (0x80)
+#define GPV1 (0x81)
+// ETC5PUD
+#define GPV2 (0x83)
+#define GPV3 (0x84)
+// ETC8PUD
+#define GPV4 (0x86)
+
+// 0x0386_0000
+#define GPZ (0x90)
+
+#define LCD_BACKLIGHT GPIO(GPB2,PIN0)
+#define LCD_RESET GPIO(GPX1,PIN5)
+#define LCD_POWER GPIO(GPX3,PIN0)
+
+/* SDHC GPIO Pin Configuration for GAIA */
+#define SD_2_EVT1_CLK GPIO(GPC3,PIN0)
+#define SD_2_EVT1_CMD GPIO(GPC3,PIN1)
+#define SD_2_EVT1_CDn GPIO(GPC3,PIN2)
+#define SD_2_EVT1_DATA0 GPIO(GPC3,PIN3)
+#define SD_2_EVT1_DATA1 GPIO(GPC3,PIN4)
+#define SD_2_EVT1_DATA2 GPIO(GPC3,PIN5)
+#define SD_2_EVT1_DATA3 GPIO(GPC3,PIN6)
+
+#define SD_2_CLK GPIO(GPC2,PIN0)
+#define SD_2_CMD GPIO(GPC2,PIN1)
+#define SD_2_CDn GPIO(GPC2,PIN2)
+#define SD_2_DATA0 GPIO(GPC2,PIN3)
+#define SD_2_DATA1 GPIO(GPC2,PIN4)
+#define SD_2_DATA2 GPIO(GPC2,PIN5)
+#define SD_2_DATA3 GPIO(GPC2,PIN6)
+#define SD_2_DATA4 GPIO(GPC3,PIN3)
+#define SD_2_DATA5 GPIO(GPC3,PIN4)
+#define SD_2_DATA6 GPIO(GPC3,PIN5)
+#define SD_2_DATA7 GPIO(GPC3,PIN6)
+
+/* USB 2.0 GPIO Pin Configuration for GAIA Evt1 */
+#define USB_2_EVT1 GPIO(GPX2,PIN6)
+
+/* SDHC CH0 GPIO Pin Configuration for GAIA */
+#define SD_0_CLK GPIO(GPC0,PIN0)
+#define SD_0_CMD GPIO(GPC0,PIN1)
+#define SD_0_CDn GPIO(GPC0,PIN2)
+#define SD_0_DATA0 GPIO(GPC0,PIN3)
+#define SD_0_DATA1 GPIO(GPC0,PIN4)
+#define SD_0_DATA2 GPIO(GPC0,PIN5)
+#define SD_0_DATA3 GPIO(GPC0,PIN6)
+#define SD_0_DATA4 GPIO(GPC1,PIN0)
+#define SD_0_DATA5 GPIO(GPC1,PIN1)
+#define SD_0_DATA6 GPIO(GPC1,PIN2)
+#define SD_0_DATA7 GPIO(GPC1,PIN3)
+
+
+#define CLK_DIV_FSYS1_OFFSET 0x1054C
+#define CLK_DIV_FSYS2_OFFSET 0x10550
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Arndale5250.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Arndale5250.h
new file mode 100644
index 000000000..0762b8aeb
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Arndale5250.h
@@ -0,0 +1,337 @@
+/*
+ * (C) Copyright 2009 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ * HeungJun Kim <riverful.kim@samsung.com>
+ * Inki Dae <inki.dae@samsung.com>
+ *
+ * Configuation settings for the SAMSUNG ARNDALE board.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+#define CONFIG_ARMV7 1 /* This is an ARM V7 CPU core */
+#define CONFIG_SAMSUNG 1 /* in a SAMSUNG core */
+#define CONFIG_S5P 1 /* which is in a S5P Family */
+#define CONFIG_ARCH_EXYNOS 1 /* which is in a Exynos Family */
+#define CONFIG_ARCH_EXYNOS5 1 /* which is in a Exynos5 Family */
+#define CONFIG_CPU_EXYNOS5250 1 /* which is in a Exynos5250 */
+#define CONFIG_MACH_SMDK5250 1 /* which is in a ARNDALE */
+#define CONFIG_EVT1 1 /* EVT1 */
+//#define CONFIG_CORTEXA5_ENABLE 1 /* enable coretex-A5(IOP) Booting */
+
+#define CONFIG_SECURE_BL1_ONLY
+//#define CONFIG_SECURE_BOOT
+#ifdef CONFIG_SECURE_BOOT
+#define CONFIG_S5PC210S
+#define CONFIG_SECURE_ROOTFS
+#define CONFIG_SECURE_KERNEL_BASE 0xc0008000
+#define CONFIG_SECURE_KERNEL_SIZE 0x200000
+#define CONFIG_SECURE_ROOTFS_BASE 0xc1000000
+#define CONFIG_SECURE_ROOTFS_SIZE 0x5c2000
+#endif
+
+//#include <asm/arch/cpu.h> /* get chip and board defs */
+
+#define CONFIG_CLK_ARM_1000_APLL_1000
+
+#define MCLK_CDREX_533 1
+#define RD_LVL 1
+
+/* (Memory Interleaving Size = 1 << IV_SIZE) */
+#define CONFIG_IV_SIZE 0x07
+
+#define CONFIG_L2_OFF
+
+//#define CONFIG_ARCH_CPU_INIT
+
+#define CONFIG_DISPLAY_CPUINFO
+//#define CONFIG_DISPLAY_BOARDINFO
+#define BOARD_LATE_INIT
+
+/* input clock of PLL: ARNDALE has 24MHz input clock */
+#define CONFIG_SYS_CLK_FREQ 24000000
+
+/* DRAM Base */
+#define CONFIG_SYS_SDRAM_BASE 0x40000000
+
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_INITRD_TAG
+#define CONFIG_CMDLINE_EDITING
+
+/* Power Management is enabled */
+//#define CONFIG_PM
+//#define CONFIG_INVERSE_PMIC_I2C 1
+#define CONFIG_PM_VDD_ARM 1.1
+#define CONFIG_PM_VDD_INT 1.0
+#define CONFIG_PM_VDD_G3D 1.1
+#define CONFIG_PM_VDD_MIF 1.1
+#define CONFIG_PM_VDD_LDO14 1.8
+
+/*
+ * Size of malloc() pool
+ * 1MB = 0x100000, 0x100000 = 1024 * 1024
+ */
+#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (1 << 20))
+ /* initial data */
+/*
+ * select serial console configuration
+ */
+#define CONFIG_SERIAL1 1
+#define CONFIG_SERIAL_MULTI 1
+
+#define CONFIG_USB_OHCI
+#undef CONFIG_USB_STORAGE
+//#define CONFIG_S3C_USBD
+#define CONFIG_EXYNOS_USBD3
+
+#define USBD_DOWN_ADDR 0xc0000000
+
+/* allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_BAUDRATE 115200
+
+/***********************************************************
+ * Command definition
+ ***********************************************************/
+
+#define CONFIG_CMD_PING
+
+#define CONFIG_CMD_USB
+
+#define CONFIG_CMD_MOVINAND
+
+#undef CONFIG_CMD_FLASH
+#undef CONFIG_CMD_IMLS
+#undef CONFIG_CMD_NAND
+
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_REGINFO
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_MOVI
+#define CONFIG_CMD_ELF
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_DEVICE
+
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+
+#define CONFIG_SYS_NAND_QUIET_TEST
+#define CONFIG_SYS_ONENAND_QUIET_TEST
+
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_S3C_HSMMC
+
+/* The macro for MMC channel 0 is defined by default and can't be undefined */
+
+/* Notice for MSHC[Using of MMC CH4] */
+/*
+ * If you want MSHC at MMC CH4.
+ */
+
+#define MMC_MAX_CHANNEL 5
+
+#define USE_MMC2
+#define USE_MMC4
+
+/*
+ * BOOTP options
+ */
+#define CONFIG_BOOTP_SUBNETMASK
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+#define CONFIG_BOOTP_BOOTPATH
+
+#define CONFIG_ETHADDR 00:40:5c:26:0a:5b
+#define CONFIG_NETMASK 255.255.255.0
+#define CONFIG_IPADDR 192.168.0.20
+#define CONFIG_SERVERIP 192.168.0.10
+#define CONFIG_GATEWAYIP 192.168.0.1
+
+#define CONFIG_BOOTDELAY 3
+/* Default boot commands for Android booting. */
+#define CONFIG_BOOTCOMMAND "movi read kernel 0 40008000;movi read rootfs 0 41000000 100000;bootm 40008000 41000000"
+#define CONFIG_BOOTARGS ""
+
+#define CONFIG_BOOTCOMMAND2 \
+ "mmc erase user 0 1072 1;" \
+ "movi r f 1 40000000;emmc open 0;movi w z f 0 40000000;emmc close 0;" \
+ "movi r u 1 40000000;emmc open 0;movi w z u 0 40000000;emmc close 0;" \
+ "movi r k 1 40000000;movi w k 0 40000000;" \
+ "movi r r 1 40000000 100000;movi w r 0 40000000 100000;" \
+ "fdisk -c 0;" \
+ "movi init 0;" \
+ "fatformat mmc 0:1;" \
+ "mmc read 1 48000000 20000 a0000;" \
+ "fastboot flash system 48000000;" \
+ "mmc read 1 48000000 c0000 a0000;" \
+ "fastboot flash userdata 48000000;" \
+ "mmc read 1 48000000 160000 a0000;" \
+ "fastboot flash cache 48000000;" \
+ "reset"
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP /* undef to save memory */
+#define CONFIG_SYS_HUSH_PARSER /* use "hush" command parser */
+#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+#define CONFIG_SYS_PROMPT "ARNDALE# "
+#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE 384 /* Print Buffer Size */
+#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+/* memtest works on */
+#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE
+#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x5e00000)
+
+#define CONFIG_SYS_HZ 1000
+
+/* valid baudrates */
+#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
+
+/*-----------------------------------------------------------------------
+ * Stack sizes
+ *
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE (256 << 10) /* 256 KiB */
+
+#define CONFIG_NR_DRAM_BANKS 4
+#define SDRAM_BANK_SIZE 0x10000000 /* 256 MB */
+#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE /* SDRAM Bank #1 */
+#define PHYS_SDRAM_1_SIZE SDRAM_BANK_SIZE
+#define PHYS_SDRAM_2 (CONFIG_SYS_SDRAM_BASE + SDRAM_BANK_SIZE) /* SDRAM Bank #2 */
+#define PHYS_SDRAM_2_SIZE SDRAM_BANK_SIZE
+#define PHYS_SDRAM_3 (CONFIG_SYS_SDRAM_BASE + 2 * SDRAM_BANK_SIZE) /* SDRAM Bank #3 */
+#define PHYS_SDRAM_3_SIZE SDRAM_BANK_SIZE
+#define PHYS_SDRAM_4 (CONFIG_SYS_SDRAM_BASE + 3 * SDRAM_BANK_SIZE) /* SDRAM Bank #4 */
+#define PHYS_SDRAM_4_SIZE SDRAM_BANK_SIZE
+#define PHYS_SDRAM_5 (CONFIG_SYS_SDRAM_BASE + 4 * SDRAM_BANK_SIZE) /* SDRAM Bank #5 */
+#define PHYS_SDRAM_5_SIZE SDRAM_BANK_SIZE
+#define PHYS_SDRAM_6 (CONFIG_SYS_SDRAM_BASE + 5 * SDRAM_BANK_SIZE) /* SDRAM Bank #6 */
+#define PHYS_SDRAM_6_SIZE SDRAM_BANK_SIZE
+#define PHYS_SDRAM_7 (CONFIG_SYS_SDRAM_BASE + 6 * SDRAM_BANK_SIZE) /* SDRAM Bank #7 */
+#define PHYS_SDRAM_7_SIZE SDRAM_BANK_SIZE
+#define PHYS_SDRAM_8 (CONFIG_SYS_SDRAM_BASE + 7 * SDRAM_BANK_SIZE) /* SDRAM Bank #8 */
+#define PHYS_SDRAM_8_SIZE SDRAM_BANK_SIZE
+
+#define CONFIG_SYS_MONITOR_BASE 0x00000000
+
+/*-----------------------------------------------------------------------
+ * FLASH and environment organization
+ */
+#define CONFIG_SYS_NO_FLASH 1
+
+#define CONFIG_SYS_MONITOR_LEN (256 << 10) /* 256 KiB */
+#define CONFIG_IDENT_STRING " for ARNDALE"
+
+#define CONFIG_ENABLE_MMU
+
+#ifdef CONFIG_ENABLE_MMU
+#define CONFIG_SYS_MAPPED_RAM_BASE 0xc0000000
+#define virt_to_phys(x) virt_to_phy_exynos5250(x)
+#else
+#define CONFIG_SYS_MAPPED_RAM_BASE CONFIG_SYS_SDRAM_BASE
+#define virt_to_phys(x) (x)
+#endif
+
+#define CONFIG_SYS_LOAD_ADDR CONFIG_SYS_MAPPED_RAM_BASE + 0x3e00000
+#define CONFIG_PHY_UBOOT_BASE CONFIG_SYS_SDRAM_BASE + 0x3e00000
+
+/*
+ * Fast Boot
+*/
+/* Fastboot variables */
+#define CFG_FASTBOOT_TRANSFER_BUFFER (0x48000000)
+#define CFG_FASTBOOT_TRANSFER_BUFFER_SIZE (0x10000000) /* 256MB */
+#define CFG_FASTBOOT_ADDR_KERNEL (0x40008000)
+#define CFG_FASTBOOT_ADDR_RAMDISK (0x40800000)
+#define CFG_FASTBOOT_PAGESIZE (2048) // Page size of booting device
+#define CFG_FASTBOOT_SDMMC_BLOCKSIZE (512) // Block size of sdmmc
+#define CFG_PARTITION_START (0x4000000)
+
+/* Just one BSP type should be defined. */
+#if defined(CONFIG_CMD_MOVINAND)
+#define CONFIG_FASTBOOT
+#endif
+
+#if defined(CONFIG_CMD_MOVINAND)
+#define CFG_FASTBOOT_SDMMCBSP
+#endif
+
+/*
+ * machine type
+ */
+
+#define MACH_TYPE 3774 /* ARNDALE machine ID */
+
+#define CONFIG_ENV_OFFSET 0x0007C000
+
+/*-----------------------------------------------------------------------
+ * Boot configuration
+ */
+#define BOOT_ONENAND 0x1
+#define BOOT_NAND 0x40000
+#define BOOT_MMCSD 0x3
+#define BOOT_NOR 0x4
+#define BOOT_SEC_DEV 0x5
+#define BOOT_EMMC 0x6
+#define BOOT_EMMC_4_4 0x7
+
+#define CONFIG_ZIMAGE_BOOT
+
+#define CONFIG_ENV_IS_IN_AUTO 1
+#define CONFIG_ENV_SIZE 0x4000
+
+#define CONFIG_DOS_PARTITION 1
+
+//#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_LOAD_ADDR - 0x1000000)
+#define CONFIG_SYS_INIT_SP_ADDR (0x43e00000 - 0x1000000)
+
+/*
+ * Ethernet Contoller driver
+ */
+#define CONFIG_CMD_NET 1
+#ifdef CONFIG_CMD_NET
+#define CONFIG_NET_MULTI
+#define CONFIG_SMC911X
+#define CONFIG_SMC911X_BASE 0x5000000
+#define CONFIG_SMC911X_16_BIT
+#endif /* CONFIG_CMD_NET */
+
+/* GPIO */
+#define GPIO_BASE 0x11400000
+
+#define CFG_PHY_UBOOT_BASE MEMORY_BASE_ADDRESS + 0x3e00000
+#define CFG_PHY_KERNEL_BASE MEMORY_BASE_ADDRESS + 0x8000
+
+#define MEMORY_BASE_ADDRESS 0x40000000
+
+#endif /* __CONFIG_H */
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Arndale5250_Val.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Arndale5250_Val.h
new file mode 100755
index 000000000..d6cdd1d9d
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Arndale5250_Val.h
@@ -0,0 +1,402 @@
+/*
+ * (C) Copyright 2012 Samsung Electronics Co. Ltd
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _VAL_ARNDALE5250_H
+#define _VAL_ARNDALE5250_H
+
+#if defined(CONFIG_CLK_ARM_800_APLL_800)
+
+#define APLL_MDIV 0x64
+#define APLL_PDIV 0x3
+#define APLL_SDIV 0x0
+
+#elif defined(CONFIG_CLK_ARM_1000_APLL_1000)
+
+#define APLL_MDIV 0x7D
+#define APLL_PDIV 0x3
+#define APLL_SDIV 0x0
+
+#elif defined(CONFIG_CLK_ARM_1200_APLL_1200)
+
+#define APLL_MDIV 0x96
+#define APLL_PDIV 0x3
+#define APLL_SDIV 0x0
+
+#elif defined(CONFIG_CLK_ARM_1400_APLL_1400)
+
+#define APLL_MDIV 0xAF
+#define APLL_PDIV 0x3
+#define APLL_SDIV 0x0
+
+#elif defined(CONFIG_CLK_ARM_1700_APLL_1700)
+
+#define APLL_MDIV 0xAF
+#define APLL_PDIV 0x3
+#define APLL_SDIV 0x0
+#endif
+
+#define MPLL_MDIV 0x64
+#define MPLL_PDIV 0x3
+#define MPLL_SDIV 0x0
+
+#define CPLL_MDIV 0xDE
+#define CPLL_PDIV 0x4
+#define CPLL_SDIV 0x2
+
+#define GPLL_MDIV 0x215
+#define GPLL_PDIV 0xC
+#define GPLL_SDIV 0x1
+
+/* APLL_CON1 */
+#define APLL_CON1_VAL (0x00203800)
+
+/* MPLL_CON1 */
+#define MPLL_CON1_VAL (0x00203800)
+
+/* CPLL_CON1 */
+#define CPLL_CON1_VAL (0x00203800)
+
+/* GPLL_CON1 */
+#define GPLL_CON1_VAL (0x00203800)
+
+#define EPLL_MDIV 0x60
+#define EPLL_PDIV 0x3
+#define EPLL_SDIV 0x3
+
+#define EPLL_CON1_VAL 0x00000000
+#define EPLL_CON2_VAL 0x00000080
+
+#define VPLL_MDIV 0x96
+#define VPLL_PDIV 0x3
+#define VPLL_SDIV 0x2
+
+/* VPLL_CON1, CON2 */
+#define VPLL_CON1_VAL 0x00000000
+#define VPLL_CON2_VAL 0x00000080
+
+#define BPLL_MDIV 0x64
+#define BPLL_PDIV 0x3
+#define BPLL_SDIV 0x0
+
+/* BPLL_CON1 */
+#define BPLL_CON1_VAL 0x00203800
+
+/* Set PLL */
+#define set_pll(mdiv, pdiv, sdiv) (1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
+
+#define APLL_CON0_VAL set_pll(APLL_MDIV, APLL_PDIV, APLL_SDIV)
+#define MPLL_CON0_VAL set_pll(MPLL_MDIV, MPLL_PDIV, MPLL_SDIV)
+#define CPLL_CON0_VAL set_pll(CPLL_MDIV, CPLL_PDIV, CPLL_SDIV)
+#define GPLL_CON0_VAL set_pll(GPLL_MDIV, GPLL_PDIV, GPLL_SDIV)
+#define EPLL_CON0_VAL set_pll(EPLL_MDIV, EPLL_PDIV, EPLL_SDIV)
+#define VPLL_CON0_VAL set_pll(VPLL_MDIV, VPLL_PDIV, VPLL_SDIV)
+#define BPLL_CON0_VAL set_pll(BPLL_MDIV, BPLL_PDIV, BPLL_SDIV)
+
+/* CLK_SRC_CPU */
+/* 0 = MOUTAPLL, 1 = SCLKMPLL */
+#define MUX_HPM_SEL 0
+#define MUX_CPU_SEL 0
+#define MUX_APLL_SEL 1
+
+#define CLK_SRC_CPU_VAL ((MUX_HPM_SEL << 20) \
+ | (MUX_CPU_SEL << 16) \
+ | (MUX_APLL_SEL))
+
+/* CLK_DIV_CPU0 */
+#if defined(CONFIG_CLK_ARM_600_APLL_600)
+#define ARM2_RATIO 0x0
+#define APLL_RATIO 0x1
+#define PCLK_DBG_RATIO 0x1
+#define ATB_RATIO 0x2
+#define PERIPH_RATIO 0x7
+#define ACP_RATIO 0x7
+#define CPUD_RATIO 0x1
+#define ARM_RATIO 0x0
+
+#elif defined(CONFIG_CLK_ARM_800_APLL_800)
+
+#define ARM2_RATIO 0x0
+#define APLL_RATIO 0x1
+#define PCLK_DBG_RATIO 0x1
+#define ATB_RATIO 0x3
+#define PERIPH_RATIO 0x7
+#define ACP_RATIO 0x7
+#define CPUD_RATIO 0x2
+#define ARM_RATIO 0x0
+
+#elif defined(CONFIG_CLK_ARM_1000_APLL_1000)
+
+#define ARM2_RATIO 0x0
+#define APLL_RATIO 0x1
+#define PCLK_DBG_RATIO 0x1
+#define ATB_RATIO 0x4
+#define PERIPH_RATIO 0x7
+#define ACP_RATIO 0x7
+#define CPUD_RATIO 0x2
+#define ARM_RATIO 0x0
+
+#elif defined(CONFIG_CLK_ARM_1200_APLL_1200)
+
+#define ARM2_RATIO 0x0
+#define APLL_RATIO 0x3
+#define PCLK_DBG_RATIO 0x1
+#define ATB_RATIO 0x5
+#define PERIPH_RATIO 0x7
+#define ACP_RATIO 0x7
+#define CPUD_RATIO 0x3
+#define ARM_RATIO 0x0
+
+#elif defined(CONFIG_CLK_ARM_1400_APLL_1400)
+
+#define ARM2_RATIO 0x0
+#define APLL_RATIO 0x3
+#define PCLK_DBG_RATIO 0x1
+#define ATB_RATIO 0x6
+#define PERIPH_RATIO 0x7
+#define ACP_RATIO 0x7
+#define CPUD_RATIO 0x3
+#define ARM_RATIO 0x0
+
+#elif defined(CONFIG_CLK_ARM_1700_APLL_1700)
+
+#define ARM2_RATIO 0x0
+#define APLL_RATIO 0x3
+#define PCLK_DBG_RATIO 0x1
+#define ATB_RATIO 0x6
+#define PERIPH_RATIO 0x7
+#define ACP_RATIO 0x7
+#define CPUD_RATIO 0x3
+#define ARM_RATIO 0x0
+#endif
+
+/* CLK_DIV_CPU0_VAL */
+#define CLK_DIV_CPU0_VAL ((ARM2_RATIO << 28) \
+ | (APLL_RATIO << 24) \
+ | (PCLK_DBG_RATIO << 20) \
+ | (ATB_RATIO << 16) \
+ | (PERIPH_RATIO << 12) \
+ | (ACP_RATIO << 8) \
+ | (CPUD_RATIO << 4) \
+ | (ARM_RATIO))
+
+/* CLK_DIV_CPU1 */
+#define HPM_RATIO 0x2
+#define COPY_RATIO 0x0
+
+/* CLK_DIV_CPU1 = 0x00000003 */
+#define CLK_DIV_CPU1_VAL ((HPM_RATIO << 4) \
+ | (COPY_RATIO))
+
+/* CLK_SRC_CORE0 */
+#define CLK_SRC_CORE0_VAL 0x00000000
+
+/* CLK_SRC_CORE1 */
+#define CLK_SRC_CORE1_VAL 0x100
+
+/* CLK_DIV_CORE0 */
+#define CLK_DIV_CORE0_VAL 0x00120000
+
+/* CLK_DIV_CORE1 */
+#define CLK_DIV_CORE1_VAL 0x07070700
+
+/* CLK_DIV_SYSRGT */
+#define CLK_DIV_SYSRGT_VAL 0x00000111
+
+/* CLK_DIV_ACP */
+#define CLK_DIV_ACP_VAL 0x12
+
+/* CLK_DIV_SYSLFT */
+#define CLK_DIV_SYSLFT_VAL 0x00000311
+
+/* CLK_SRC_CDREX */
+#define CLK_SRC_CDREX_VAL 0x1
+
+/* CLK_DIV_CDREX */
+#define MCLK_DPHY_RATIO 0x1
+#define MCLK_CDREX_RATIO 0x1
+#define ACLK_C2C_200_RATIO 0x1
+#define C2C_CLK_400_RATIO 0x1
+#define PCLK_CDREX_RATIO 0x1
+#define ACLK_CDREX_RATIO 0x1
+
+#define CLK_DIV_CDREX_VAL ((MCLK_DPHY_RATIO << 20) \
+ | (MCLK_CDREX_RATIO << 16) \
+ | (ACLK_C2C_200_RATIO << 12) \
+ | (C2C_CLK_400_RATIO << 8) \
+ | (PCLK_CDREX_RATIO << 4) \
+ | (ACLK_CDREX_RATIO)) \
+/* CLK_SRC_TOP0 */
+#define MUX_ACLK_300_GSCL_SEL 0x0
+#define MUX_ACLK_300_GSCL_MID_SEL 0x0
+#define MUX_ACLK_400_G3D_MID_SEL 0x0
+#define MUX_ACLK_333_SEL 0x0
+#define MUX_ACLK_300_DISP1_SEL 0x0
+#define MUX_ACLK_300_DISP1_MID_SEL 0x0
+#define MUX_ACLK_200_SEL 0x0
+#define MUX_ACLK_166_SEL 0x0
+#define CLK_SRC_TOP0_VAL ((MUX_ACLK_300_GSCL_SEL << 25) \
+ | (MUX_ACLK_300_GSCL_MID_SEL << 24) \
+ | (MUX_ACLK_400_G3D_MID_SEL << 20) \
+ | (MUX_ACLK_333_SEL << 16) \
+ | (MUX_ACLK_300_DISP1_SEL << 15) \
+ | (MUX_ACLK_300_DISP1_MID_SEL << 14) \
+ | (MUX_ACLK_200_SEL << 12) \
+ | (MUX_ACLK_166_SEL << 8))
+
+/* CLK_SRC_TOP1 */
+#define MUX_ACLK_400_G3D_SEL 0x1
+#define MUX_ACLK_400_ISP_SEL 0x0
+#define MUX_ACLK_400_IOP_SEL 0x0
+#define MUX_ACLK_MIPI_HSI_TXBASE_SEL 0x0
+#define MUX_ACLK_300_GSCL_MID1_SEL 0x0
+#define MUX_ACLK_300_DISP1_MID1_SEL 0x0
+#define CLK_SRC_TOP1_VAL ((MUX_ACLK_400_G3D_SEL << 28) \
+ |(MUX_ACLK_400_ISP_SEL << 24) \
+ |(MUX_ACLK_400_IOP_SEL << 20) \
+ |(MUX_ACLK_MIPI_HSI_TXBASE_SEL << 16) \
+ |(MUX_ACLK_300_GSCL_MID1_SEL << 12) \
+ |(MUX_ACLK_300_DISP1_MID1_SEL << 8))
+
+/* CLK_SRC_TOP2 */
+#define MUX_GPLL_SEL 0x1
+#define MUX_BPLL_USER_SEL 0x0
+#define MUX_MPLL_USER_SEL 0x0
+#define MUX_VPLL_SEL 0x1
+#define MUX_EPLL_SEL 0x1
+#define MUX_CPLL_SEL 0x1
+#define VPLLSRC_SEL 0x0
+#define CLK_SRC_TOP2_VAL ((MUX_GPLL_SEL << 28) \
+ | (MUX_BPLL_USER_SEL << 24) \
+ | (MUX_MPLL_USER_SEL << 20) \
+ | (MUX_VPLL_SEL << 16) \
+ | (MUX_EPLL_SEL << 12) \
+ | (MUX_CPLL_SEL << 8) \
+ | (VPLLSRC_SEL))
+/* CLK_SRC_TOP3 */
+#define MUX_ACLK_333_SUB_SEL 0x1
+#define MUX_ACLK_400_SUB_SEL 0x1
+#define MUX_ACLK_266_ISP_SUB_SEL 0x1
+#define MUX_ACLK_266_GPS_SUB_SEL 0x0
+#define MUX_ACLK_300_GSCL_SUB_SEL 0x1
+#define MUX_ACLK_266_GSCL_SUB_SEL 0x1
+#define MUX_ACLK_300_DISP1_SUB_SEL 0x1
+#define MUX_ACLK_200_DISP1_SUB_SEL 0x1
+#define CLK_SRC_TOP3_VAL ((MUX_ACLK_333_SUB_SEL << 24) \
+ | (MUX_ACLK_400_SUB_SEL << 20) \
+ | (MUX_ACLK_266_ISP_SUB_SEL << 16) \
+ | (MUX_ACLK_266_GPS_SUB_SEL << 12) \
+ | (MUX_ACLK_300_GSCL_SUB_SEL << 10) \
+ | (MUX_ACLK_266_GSCL_SUB_SEL << 8) \
+ | (MUX_ACLK_300_DISP1_SUB_SEL << 6) \
+ | (MUX_ACLK_200_DISP1_SUB_SEL << 4))
+
+/* CLK_DIV_TOP0 */
+#define ACLK_300_DISP1_RATIO 0x2
+#define ACLK_400_G3D_RATIO 0x0
+#define ACLK_333_RATIO 0x0
+#define ACLK_266_RATIO 0x2
+#define ACLK_200_RATIO 0x3
+#define ACLK_166_RATIO 0x1
+#define ACLK_133_RATIO 0x1
+#define ACLK_66_RATIO 0x5
+
+#define CLK_DIV_TOP0_VAL ((ACLK_300_DISP1_RATIO << 28) \
+ | (ACLK_400_G3D_RATIO << 24) \
+ | (ACLK_333_RATIO << 20) \
+ | (ACLK_266_RATIO << 16) \
+ | (ACLK_200_RATIO << 12) \
+ | (ACLK_166_RATIO << 8) \
+ | (ACLK_133_RATIO << 4) \
+ | (ACLK_66_RATIO))
+
+/* CLK_DIV_TOP1 */
+#define ACLK_MIPI_HSI_TX_BASE_RATIO 0x3
+#define ACLK_66_PRE_RATIO 0x1
+#define ACLK_400_ISP_RATIO 0x1
+#define ACLK_400_IOP_RATIO 0x1
+#define ACLK_300_GSCL_RATIO 0x2
+
+#define CLK_DIV_TOP1_VAL ((ACLK_MIPI_HSI_TX_BASE_RATIO << 28) \
+ | (ACLK_66_PRE_RATIO << 24) \
+ | (ACLK_400_ISP_RATIO << 20) \
+ | (ACLK_400_IOP_RATIO << 16) \
+ | (ACLK_300_GSCL_RATIO << 12))
+
+/* APLL_LOCK */
+#define APLL_LOCK_VAL (0x546)
+/* MPLL_LOCK */
+#define MPLL_LOCK_VAL (0x546)
+/* CPLL_LOCK */
+#define CPLL_LOCK_VAL (0x546)
+/* GPLL_LOCK */
+#define GPLL_LOCK_VAL (0x546)
+/* EPLL_LOCK */
+#define EPLL_LOCK_VAL (0x3A98)
+/* VPLL_LOCK */
+#define VPLL_LOCK_VAL (0x3A98)
+/* BPLL_LOCK */
+#define BPLL_LOCK_VAL (0x546)
+
+/* CLK_SRC_PERIC0 */
+#define PWM_SEL 0
+#define UART3_SEL 6
+#define UART2_SEL 6
+#define UART1_SEL 6
+#define UART0_SEL 6
+/* SRC_CLOCK = SCLK_MPLL */
+#define CLK_SRC_PERIC0_VAL ((PWM_SEL << 24) \
+ | (UART3_SEL << 12) \
+ | (UART2_SEL<< 8) \
+ | (UART1_SEL << 4) \
+ | (UART0_SEL))
+
+/* CLK_DIV_PERIL0 */
+#define UART5_RATIO 7
+#define UART4_RATIO 7
+#define UART3_RATIO 7
+#define UART2_RATIO 7
+#define UART1_RATIO 7
+#define UART0_RATIO 7
+
+#define CLK_DIV_PERIC0_VAL ((UART3_RATIO << 12) \
+ | (UART2_RATIO << 8) \
+ | (UART1_RATIO << 4) \
+ | (UART0_RATIO))
+/* CLK_SRC_LEX */
+#define CLK_SRC_LEX_VAL 0x0
+
+/* CLK_DIV_LEX */
+#define CLK_DIV_LEX_VAL 0x10
+
+/* CLK_DIV_R0X */
+#define CLK_DIV_R0X_VAL 0x10
+
+/* CLK_DIV_L0X */
+#define CLK_DIV_R1X_VAL 0x10
+
+/* CLK_DIV_ISP0 */
+#define CLK_DIV_ISP0_VAL 0x31
+
+/* CLK_DIV_ISP1 */
+#define CLK_DIV_ISP1_VAL 0x0
+
+/* CLK_DIV_ISP2 */
+#define CLK_DIV_ISP2_VAL 0x1
+
+#define MPLL_DEC (MPLL_MDIV * MPLL_MDIV / (MPLL_PDIV * 2^(MPLL_SDIV-1)))
+
+#define SCLK_UART MPLL_DEC / (UART1_RATIO+1)
+
+#define UART_UBRDIV_VAL 0x35 /* (SCLK_UART/(115200*16) -1) */
+#define UART_UDIVSLOT_VAL 0x4 /*((((SCLK_UART*10/(115200*16) -10))%10)*16/10)*/
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Exynos5250.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Exynos5250.h
new file mode 100644
index 000000000..b0e473d9e
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Exynos5250.h
@@ -0,0 +1,730 @@
+/*
+ * (C) Copyright 2012 Samsung Electronics Co. Ltd
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _EXYNOS5250_CPU_H
+#define _EXYNOS5250_CPU_H
+
+/* EXYNOS5250 */
+#define EXYNOS5250_PRO_ID 0x10000000
+#define EXYNOS5250_SYSREG_BASE 0x10050000
+#define EXYNOS5250_POWER_BASE 0x10040000
+#define EXYNOS5250_CLOCK_BASE 0x10010000
+#define EXYNOS5250_SROM_BASE 0x12250000
+#define EXYNOS5250_HSMMC_BASE 0x12200000
+#define EXYNOS5250_PWMTIMER_BASE 0x12DD0000
+#define EXYNOS5250_INF_REG_BASE 0x10040800
+#define EXYNOS5250_TZPC_BASE 0x10100000
+#define EXYNOS5250_UART_BASE 0x12C00000
+
+#define BIT0 0x00000001
+#define BIT1 0x00000002
+#define BIT2 0x00000004
+#define BIT3 0x00000008
+#define BIT4 0x00000010
+#define BIT5 0x00000020
+#define BIT6 0x00000040
+#define BIT7 0x00000080
+#define BIT8 0x00000100
+#define BIT9 0x00000200
+#define BIT10 0x00000400
+#define BIT11 0x00000800
+#define BIT12 0x00001000
+#define BIT13 0x00002000
+#define BIT14 0x00004000
+#define BIT15 0x00008000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+
+
+#define __REG(x) (*(unsigned int *)(x))
+
+/*
+ * CHIP ID
+ */
+#define CHIP_ID_BASE EXYNOS5250_PRO_ID
+#define PRO_ID_OFFSET 0x0
+#define PRO_ID __REG(CHIP_ID_BASE+PRO_ID_OFFSET)
+
+/*
+ * SYSREG
+ */
+#define USB_CFG_OFFSET 0x230
+#define USB_CFG_REG (EXYNOS5250_SYSREG_BASE + USB_CFG_OFFSET)
+
+/*
+ * POWER
+ */
+#define ELFIN_POWER_BASE EXYNOS5250_POWER_BASE
+#define OMR_OFFSET 0x0
+#define SW_RST_REG_OFFSET 0x400
+#define SW_RST_REG __REG(EXYNOS5250_POWER_BASE + SW_RST_REG_OFFSET)
+
+#define INF_REG_BASE EXYNOS5250_INF_REG_BASE
+
+#define INF_REG0_OFFSET 0x00
+#define INF_REG1_OFFSET 0x04
+#define INF_REG2_OFFSET 0x08
+#define INF_REG3_OFFSET 0x0C
+#define INF_REG4_OFFSET 0x10
+#define INF_REG5_OFFSET 0x14
+#define INF_REG6_OFFSET 0x18
+#define INF_REG7_OFFSET 0x1C
+
+#define INF_REG0_REG __REG(INF_REG_BASE+INF_REG0_OFFSET)
+#define INF_REG1_REG __REG(INF_REG_BASE+INF_REG1_OFFSET)
+#define INF_REG2_REG __REG(INF_REG_BASE+INF_REG2_OFFSET)
+#define INF_REG3_REG __REG(INF_REG_BASE+INF_REG3_OFFSET)
+#define INF_REG4_REG __REG(INF_REG_BASE+INF_REG4_OFFSET)
+#define INF_REG5_REG __REG(INF_REG_BASE+INF_REG5_OFFSET)
+#define INF_REG6_REG __REG(INF_REG_BASE+INF_REG6_OFFSET)
+#define INF_REG7_REG __REG(INF_REG_BASE+INF_REG7_OFFSET)
+
+#define USB_DEVICE_PHY_CONTROL_OFFSET 0x0704
+#define USB_DEVICE_PHY_CONTROL (EXYNOS5250_POWER_BASE+USB_DEVICE_PHY_CONTROL_OFFSET)
+
+/* Define Mode */
+#define S5P_CHECK_SLEEP 0x00000BAD
+#define S5P_CHECK_DIDLE 0xBAD00000
+#define S5P_CHECK_LPA 0xABAD0000
+
+/*
+ * CLOCK
+ */
+#define ELFIN_CLOCK_BASE EXYNOS5250_CLOCK_BASE
+
+#define APLL_LOCK_OFFSET 0x00000
+#define APLL_CON0_OFFSET 0x00100
+#define APLL_CON1_OFFSET 0x00104
+#define CLK_SRC_CPU_OFFSET 0x00200
+#define CLK_MUX_STAT_CPU_OFFSET 0x00400
+#define CLK_DIV_CPU0_OFFSET 0x00500
+#define CLK_DIV_CPU1_OFFSET 0x00504
+#define CLK_DIV_STAT_CPU0_OFFSET 0x00600
+#define CLK_DIV_STAT_CPU1_OFFSET 0x00604
+#define CLK_GATE_SCLK_CPU_OFFSET 0x00800
+#define CLKOUT_CMU_CPU_OFFSET 0x00A00
+#define CLKOUT_CMU_CPU_DIV_STAT_OFFSET 0x00A04
+#define ARMCLK_STOPCTRL_OFFSET 0x01000
+#define ATCLK_STOPCTRL_OFFSET 0x01004
+#define PARITYFAIL_STATUS_OFFSET 0x01010
+#define PARITYFAIL_CLEAR_OFFSET 0x01014
+#define PWR_CTRL_OFFSET 0x01020
+#define PWR_CTRL2_OFFSET 0x01024
+#define APLL_CON0_L8_OFFSET 0x01100
+#define APLL_CON0_L7_OFFSET 0x01104
+#define APLL_CON0_L6_OFFSET 0x01108
+#define APLL_CON0_L5_OFFSET 0x0110C
+#define APLL_CON0_L4_OFFSET 0x01110
+#define APLL_CON0_L3_OFFSET 0x01114
+#define APLL_CON0_L2_OFFSET 0x01118
+#define APLL_CON0_L1_OFFSET 0x0111C
+#define IEM_CONTROL_OFFSET 0x01120
+#define APLL_CON1_L8_OFFSET 0x01200
+#define APLL_CON1_L7_OFFSET 0x01204
+#define APLL_CON1_L6_OFFSET 0x01208
+#define APLL_CON1_L5_OFFSET 0x0120C
+#define APLL_CON1_L4_OFFSET 0x01210
+#define APLL_CON1_L3_OFFSET 0x01214
+#define APLL_CON1_L2_OFFSET 0x01218
+#define APLL_CON1_L1_OFFSET 0x0121C
+#define CLKDIV_IEM_L8_OFFSET 0x01300
+#define CLKDIV_IEM_L7_OFFSET 0x01304
+#define CLKDIV_IEM_L6_OFFSET 0x01308
+#define CLKDIV_IEM_L5_OFFSET 0x0130C
+#define CLKDIV_IEM_L4_OFFSET 0x01310
+#define CLKDIV_IEM_L3_OFFSET 0x01314
+#define CLKDIV_IEM_L2_OFFSET 0x01318
+#define CLKDIV_IEM_L1_OFFSET 0x0131C
+#define MPLL_LOCK_OFFSET 0x04000
+#define MPLL_CON0_OFFSET 0x04100
+#define MPLL_CON1_OFFSET 0x04104
+#define CLK_SRC_CORE0_OFFSET 0x04200
+#define CLK_SRC_CORE1_OFFSET 0x04204
+#define CLK_SRC_MASK_CORE0_OFFSET 0x04300
+#define CLK_MUX_STAT_CORE1_OFFSET 0x04404
+#define CLK_DIV_CORE0_OFFSET 0x04500
+#define CLK_DIV_CORE1_OFFSET 0x04504
+#define CLK_DIV_STAT_CORE0_OFFSET 0x04600
+#define CLK_DIV_STAT_CORE1_OFFSET 0x04604
+#define CLK_GATE_IP_CORE_OFFSET 0x04900
+#define CLKOUT_CMU_CORE_OFFSET 0x04A00
+#define CLKOUT_CMU_CORE_DIV_STAT_OFFSET 0x04A04
+#define DCGIDX_MAP0_OFFSET 0x05000
+#define DCGIDX_MAP1_OFFSET 0x05004
+#define DCGIDX_MAP2_OFFSET 0x05008
+#define DCGPERF_MAP0_OFFSET 0x05020
+#define DCGPERF_MAP1_OFFSET 0x05024
+#define DVCIDX_MAP_OFFSET 0x05040
+#define FREQ_CPU_OFFSET 0x05060
+#define FREQ_DPM_OFFSET 0x05064
+#define DVSEMCLK_EN_OFFSET 0x05080
+#define MAXPERF_OFFSET 0x05084
+#define CLK_DIV_ACP_OFFSET 0x08500
+#define CLK_DIV_STAT_ACP_OFFSET 0x08600
+#define CLK_GATE_IP_ACP_OFFSET 0x08800
+#define CLKOUT_CMU_ACP_OFFSET 0x08A00
+#define CLKOUT_CMU_ACP_DIV_STAT_OFFSET 0x08A04
+#define CLK_DIV_ISP0_OFFSET 0x0C300
+#define CLK_DIV_ISP1_OFFSET 0x0C304
+#define CLK_DIV_ISP2_OFFSET 0x0C308
+#define CLK_DIV_STAT_ISP0_OFFSET 0x0C400
+#define CLK_DIV_STAT_ISP1_OFFSET 0x0C404
+#define CLK_DIV_STAT_ISP2_OFFSET 0x0C408
+#define CLK_GATE_IP_ISP0_OFFSET 0x0C800
+#define CLK_GATE_IP_ISP1_OFFSET 0x0C804
+#define CLK_GATE_SCLK_ISP_OFFSET 0x0C900
+#define MCUISP_PWR_CTRL_OFFSET 0x0C910
+#define CLKOUT_CMU_ISP_OFFSET 0x0CA00
+#define CLKOUT_CMU_ISP_DIV_STAT_OFFSET 0x0CA04
+#define CPLL_LOCK_OFFSET 0x10020
+#define EPLL_LOCK_OFFSET 0x10030
+#define VPLL_LOCK_OFFSET 0x10040
+#define CPLL_CON0_OFFSET 0x10120
+#define CPLL_CON1_OFFSET 0x10124
+#define EPLL_CON0_OFFSET 0x10130
+#define EPLL_CON1_OFFSET 0x10134
+#define EPLL_CON2_OFFSET 0x10138
+#define VPLL_CON0_OFFSET 0x10140
+#define VPLL_CON1_OFFSET 0x10144
+#define VPLL_CON2_OFFSET 0x10148
+#define CLK_SRC_TOP0_OFFSET 0x10210
+#define CLK_SRC_TOP1_OFFSET 0x10214
+#define CLK_SRC_TOP2_OFFSET 0x10218
+#define CLK_SRC_TOP3_OFFSET 0x1021C
+#define CLK_SRC_GSCL_OFFSET 0x10220
+#define CLK_SRC_DISP1_0_OFFSET 0x1022C
+#define CLK_SRC_DISP1_1_OFFSET 0x10230
+#define CLK_SRC_MAU_OFFSET 0x10240
+#define CLK_SRC_FSYS_OFFSET 0x10244
+#define CLK_SRC_PERIC0_OFFSET 0x10250
+#define CLK_SRC_PERIC1_OFFSET 0x10254
+#define SCLK_SRC_ISP_OFFSET 0x10270
+#define CLK_SRC_MASK_TOP_OFFSET 0x10310
+#define CLK_SRC_MASK_GSCL_OFFSET 0x10320
+#define CLK_SRC_MASK_DISP1_0_OFFSET 0x1032C
+#define CLK_SRC_MASK_DISP1_1_OFFSET 0x10330
+#define CLK_SRC_MASK_MAU_OFFSET 0x10334
+#define CLK_SRC_MASK_FSYS_OFFSET 0x10340
+#define CLK_SRC_MASK_PERIC0_OFFSET 0x10350
+#define CLK_SRC_MASK_PERIC1_OFFSET 0x10354
+#define SCLK_SRC_MASK_ISP_OFFSET 0x10370
+#define CLK_MUX_STAT_TOP0_OFFSET 0x10410
+#define CLK_MUX_STAT_TOP1_OFFSET 0x10414
+#define CLK_MUX_STAT_TOP2_OFFSET 0x10418
+#define CLK_MUX_STAT_TOP3_OFFSET 0x1041C
+#define CLK_DIV_TOP0_OFFSET 0x10510
+#define CLK_DIV_TOP1_OFFSET 0x10514
+#define CLK_DIV_GSCL_OFFSET 0x10520
+#define CLK_DIV_DISP1_0_OFFSET 0x1052C
+#define CLK_DIV_DISP1_1_OFFSET 0x10530
+#define CLK_DIV_GEN_OFFSET 0x1053C
+#define CLK_DIV_MAU_OFFSET 0x10544
+#define CLK_DIV_FSYS0_OFFSET 0x10548
+#define CLK_DIV_FSYS1_OFFSET 0x1054C
+#define CLK_DIV_FSYS2_OFFSET 0x10550
+#define CLK_DIV_FSYS3_OFFSET 0x10554
+#define CLK_DIV_PERIC0_OFFSET 0x10558
+#define CLK_DIV_PERIC1_OFFSET 0x1055C
+#define CLK_DIV_PERIC2_OFFSET 0x10560
+#define CLK_DIV_PERIC3_OFFSET 0x10564
+#define CLK_DIV_PERIC4_OFFSET 0x10568
+#define CLK_DIV_PERIC5_OFFSET 0x1056C
+#define SCLK_DIV_ISP_OFFSET 0x10580
+#define CLKDIV2_RATIO0_OFFSET 0x10590
+#define CLKDIV2_RATIO1_OFFSET 0x10594
+#define CLKDIV4_RATIO_OFFSET 0x105A0
+#define CLK_DIV_STAT_TOP0_OFFSET 0x10610
+#define CLK_DIV_STAT_TOP1_OFFSET 0x10614
+#define CLK_DIV_STAT_GSCL_OFFSET 0x10620
+#define CLK_DIV_STAT_DISP1_0_OFFSET 0x1062C
+#define CLK_DIV_STAT_DISP1_1_OFFSET 0x10630
+#define CLK_DIV_STAT_GEN_OFFSET 0x1063C
+#define CLK_DIV_STAT_MAUDIO_OFFSET 0x10644
+#define CLK_DIV_STAT_FSYS0_OFFSET 0x10648
+#define CLK_DIV_STAT_FSYS1_OFFSET 0x1064C
+#define CLK_DIV_STAT_FSYS2_OFFSET 0x10650
+#define CLK_DIV_STAT_FSYS3_OFFSET 0x10654
+#define CLK_DIV_STAT_PERIC0_OFFSET 0x10658
+#define CLK_DIV_STAT_PERIC1_OFFSET 0x1065C
+#define CLK_DIV_STAT_PERIC2_OFFSET 0x10660
+#define CLK_DIV_STAT_PERIC3_OFFSET 0x10664
+#define CLK_DIV_STAT_PERIC4_OFFSET 0x10668
+#define CLK_DIV_STAT_PERIC5_OFFSET 0x1066C
+#define SCLK_DIV_STAT_ISP_OFFSET 0x10680
+#define CLKDIV2_STAT0_OFFSET 0x10690
+#define CLKDIV2_STAT1_OFFSET 0x10694
+#define CLKDIV4_STAT_OFFSET 0x106A0
+#define CLK_GATE_TOP_SCLK_DISP1_OFFSET 0x10828
+#define CLK_GATE_TOP_SCLK_GEN_OFFSET 0x1082C
+#define CLK_GATE_TOP_SCLK_MAU_OFFSET 0x1083C
+#define CLK_GATE_TOP_SCLK_FSYS_OFFSET 0x10840
+#define CLK_GATE_TOP_SCLK_PERIC_OFFSET 0x10850
+#define CLK_GATE_TOP_SCLK_ISP_OFFSET 0x10870
+#define CLK_GATE_IP_GSCL_OFFSET 0x10920
+#define CLK_GATE_IP_DISP1_OFFSET 0x10928
+#define CLK_GATE_IP_MFC_OFFSET 0x1092C
+#define CLK_GATE_IP_G3D_OFFSET 0x10930
+#define CLK_GATE_IP_GEN_OFFSET 0x10934
+#define CLK_GATE_IP_FSYS_OFFSET 0x10944
+#define CLK_GATE_IP_GPS_OFFSET 0x1094C
+#define CLK_GATE_IP_PERIC_OFFSET 0x10950
+#define CLK_GATE_IP_PERIS_OFFSET 0x10960
+#define CLK_GATE_BLOCK_OFFSET 0x10980
+#define CLKOUT_CMU_TOP_OFFSET 0x10A00
+#define CLKOUT_CMU_TOP_DIV_STAT_OFFSET 0x10A04
+#define CLK_SRC_LEX_OFFSET 0x14200
+#define CLK_DIV_LEX_OFFSET 0x14500
+#define CLK_DIV_STAT_LEX_OFFSET 0x14600
+#define CLK_GATE_IP_LEX_OFFSET 0x14800
+#define CLKOUT_CMU_LEX_OFFSET 0x14A00
+#define CLKOUT_CMU_LEX_DIV_STAT_OFFSET 0x14A04
+#define CLK_DIV_R0X_OFFSET 0x18500
+#define CLK_DIV_STAT_R0X_OFFSET 0x18600
+#define CLK_GATE_IP_R0X_OFFSET 0x18800
+#define CLKOUT_CMU_R0X_OFFSET 0x18A00
+#define CLKOUT_CMU_R0X_DIV_STAT_OFFSET 0x18A04
+#define CLK_DIV_R1X_OFFSET 0x1C500
+#define CLK_DIV_STAT_R1X_OFFSET 0x1C600
+#define CLK_GATE_IP_R1X_OFFSET 0x1C800
+#define CLKOUT_CMU_R1X_OFFSET 0x1CA00
+#define CLKOUT_CMU_R1X_DIV_STAT_OFFSET 0x1CA04
+#define BPLL_LOCK_OFFSET 0x20010
+#define BPLL_CON0_OFFSET 0x20110
+#define BPLL_CON1_OFFSET 0x20114
+#define CLK_SRC_CDREX_OFFSET 0x20200
+#define CLK_MUX_STAT_CDREX_OFFSET 0x20400
+#define CLK_DIV_CDREX_OFFSET 0x20500
+#define CLK_DIV_CDREX2_OFFSET 0x20504
+#define CLK_DIV_STAT_CDREX_OFFSET 0x20600
+#define CLK_GATE_IP_CDREX_OFFSET 0x20900
+#define C2C_MONITOR_OFFSET 0x20910
+#define DMC_PWR_CTRL 0x20914
+#define DREX2_PAUSE_OFFSET 0x2091C
+#define CLKOUT_CMU_CDREX_OFFSET 0x20A00
+#define CLKOUT_CMU_CDREX_DIV_STAT_OFFSET 0x20A04
+#define LPDDR3PHY_CTRL 0x20A10
+
+#define CLK_SRC_FSYS __REG(ELFIN_CLOCK_BASE+CLK_SRC_FSYS_OFFSET)
+#define CLK_DIV_FSYS1 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS1_OFFSET)
+#define CLK_DIV_FSYS2 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS2_OFFSET)
+#define CLK_DIV_FSYS3 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS3_OFFSET)
+#define APLL_CON0_REG __REG(ELFIN_CLOCK_BASE+APLL_CON0_OFFSET)
+#define MPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+MPLL_CON0_OFFSET)
+#define EPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+EPLL_CON0_OFFSET)
+#define VPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+VPLL_CON0_OFFSET)
+
+#define FIMD1_SCLKMPLL (0x06)
+#define FIMD1_CLK_DIV (0x00)
+
+#define CLK_GATE_FIMD1_MASK (0x01 << 0x00)
+#define CLK_SRC_FIMD1_MASK (0x0F << 0x00)
+#define CLK_DIV_FIMD1_MASK (0x0F << 0x00)
+
+#define CLK_SRC_FIMD1_SEL(x) ((x) << 0x00)
+#define CLK_DIV_FIMD1_SEL(x) ((x) << 0x00)
+#define CLK_SRC_DISP1_0_UNMASK (0x01 << 0x00)
+
+#define CLK_GATE_DSIM1_MASK (0x01 << 0x03)
+
+/*
+ * TZPC
+ */
+#define TZPC0_OFFSET 0x00000
+#define TZPC1_OFFSET 0x10000
+#define TZPC2_OFFSET 0x20000
+#define TZPC3_OFFSET 0x30000
+#define TZPC4_OFFSET 0x40000
+#define TZPC5_OFFSET 0x50000
+#define TZPC6_OFFSET 0x60000
+#define TZPC7_OFFSET 0x70000
+#define TZPC8_OFFSET 0x80000
+#define TZPC9_OFFSET 0x90000
+
+#define ELFIN_TZPC0_BASE (EXYNOS5250_TZPC_BASE + TZPC0_OFFSET)
+#define ELFIN_TZPC1_BASE (EXYNOS5250_TZPC_BASE + TZPC1_OFFSET)
+#define ELFIN_TZPC2_BASE (EXYNOS5250_TZPC_BASE + TZPC2_OFFSET)
+#define ELFIN_TZPC3_BASE (EXYNOS5250_TZPC_BASE + TZPC3_OFFSET)
+#define ELFIN_TZPC4_BASE (EXYNOS5250_TZPC_BASE + TZPC4_OFFSET)
+#define ELFIN_TZPC5_BASE (EXYNOS5250_TZPC_BASE + TZPC5_OFFSET)
+#define ELFIN_TZPC6_BASE (EXYNOS5250_TZPC_BASE + TZPC6_OFFSET)
+#define ELFIN_TZPC7_BASE (EXYNOS5250_TZPC_BASE + TZPC7_OFFSET)
+#define ELFIN_TZPC8_BASE (EXYNOS5250_TZPC_BASE + TZPC8_OFFSET)
+#define ELFIN_TZPC9_BASE (EXYNOS5250_TZPC_BASE + TZPC9_OFFSET)
+
+#define TZPC_DECPROT0SET_OFFSET 0x804
+#define TZPC_DECPROT1SET_OFFSET 0x810
+#define TZPC_DECPROT2SET_OFFSET 0x81C
+#define TZPC_DECPROT3SET_OFFSET 0x828
+
+/*
+ * Memory controller
+ */
+#define ELFIN_SROM_BASE EXYNOS5250_SROM_BASE
+
+#define SROM_BW_REG __REG(ELFIN_SROM_BASE+0x0)
+#define SROM_BC0_REG __REG(ELFIN_SROM_BASE+0x4)
+#define SROM_BC1_REG __REG(ELFIN_SROM_BASE+0x8)
+#define SROM_BC2_REG __REG(ELFIN_SROM_BASE+0xC)
+#define SROM_BC3_REG __REG(ELFIN_SROM_BASE+0x10)
+
+/*
+ * SDRAM Controller
+ */
+
+/* DMC control register */
+#define DMC_CTRL_BASE 0x10DD0000
+
+#define DMC_CONCONTROL 0x00
+#define DMC_MEMCONTROL 0x04
+#define DMC_MEMCONFIG0 0x08
+#define DMC_MEMCONFIG1 0x0C
+#define DMC_DIRECTCMD 0x10
+#define DMC_PRECHCONFIG 0x14
+#define DMC_PHYCONTROL0 0x18
+#define DMC_PWRDNCONFIG 0x28
+#define DMC_TIMINGPZQ 0x2C
+#define DMC_TIMINGAREF 0x30
+#define DMC_TIMINGROW 0x34
+#define DMC_TIMINGDATA 0x38
+#define DMC_TIMINGPOWER 0x3C
+#define DMC_PHYSTATUS 0x40
+#define DMC_CHIPSTATUS_CH0 0x48
+#define DMC_CHIPSTATUS_CH1 0x4C
+#define DMC_MRSTATUS 0x54
+#define DMC_QOSCONTROL0 0x60
+#define DMC_QOSCONTROL1 0x68
+#define DMC_QOSCONTROL2 0x70
+#define DMC_QOSCONTROL3 0x78
+#define DMC_QOSCONTROL4 0x80
+#define DMC_QOSCONTROL5 0x88
+#define DMC_QOSCONTROL6 0x90
+#define DMC_QOSCONTROL7 0x98
+#define DMC_QOSCONTROL8 0xA0
+#define DMC_QOSCONTROL9 0xA8
+#define DMC_QOSCONTROL10 0xB0
+#define DMC_QOSCONTROL11 0xB8
+#define DMC_QOSCONTROL12 0xC0
+#define DMC_QOSCONTROL13 0xC8
+#define DMC_QOSCONTROL14 0xD0
+#define DMC_QOSCONTROL15 0xD8
+#define DMC_IVCONTROL 0xF0
+#define DMC_WRTRA_CONFIG 0x00F4
+#define DMC_RDLVL_CONFIG 0x00F8
+#define DMC_BRBRSVCONTROL 0x0100
+#define DMC_BRBRSVCONFIG 0x0104
+#define DMC_BRBQOSCONFIG 0x0108
+#define DMC_MEMBASECONFIG0 0x010C
+#define DMC_MEMBASECONFIG1 0x0110
+#define DMC_WRLVL_CONFIG 0x0120
+#define DMC_PMNC_PPC 0xE000
+#define DMC_CNTENS_PPC 0xE010
+#define DMC_CNTENC_PPC 0xE020
+#define DMC_INTENS_PPC 0xE030
+#define DMC_INTENC_PPC 0xE040
+#define DMC_FLAG_PPC 0xE050
+#define DMC_CCNT_PPC 0xE100
+#define DMC_PMCNT0_PPC 0xE110
+#define DMC_PMCNT1_PPC 0xE120
+#define DMC_PMCNT2_PPC 0xE130
+#define DMC_PMCNT3_PPC 0xE140
+
+/* PHY Control Register */
+#define PHY0_CTRL_BASE 0x10C00000
+#define PHY1_CTRL_BASE 0x10C10000
+
+#define DMC_PHY_CON0 0x00
+#define DMC_PHY_CON1 0x04
+#define DMC_PHY_CON2 0x08
+#define DMC_PHY_CON3 0x0C
+#define DMC_PHY_CON4 0x10
+#define DMC_PHY_CON6 0x18
+#define DMC_PHY_CON8 0x20
+#define DMC_PHY_CON10 0x28
+#define DMC_PHY_CON11 0x2C
+#define DMC_PHY_CON12 0x30
+#define DMC_PHY_CON13 0x34
+#define DMC_PHY_CON14 0x38
+#define DMC_PHY_CON15 0x3C
+#define DMC_PHY_CON16 0x40
+#define DMC_PHY_CON17 0x48
+#define DMC_PHY_CON18 0x4C
+#define DMC_PHY_CON19 0x50
+#define DMC_PHY_CON20 0x54
+#define DMC_PHY_CON21 0x58
+#define DMC_PHY_CON22 0x5C
+#define DMC_PHY_CON23 0x60
+#define DMC_PHY_CON24 0x64
+#define DMC_PHY_CON25 0x68
+#define DMC_PHY_CON26 0x6C
+#define DMC_PHY_CON27 0x70
+#define DMC_PHY_CON28 0x74
+#define DMC_PHY_CON29 0x78
+#define DMC_PHY_CON30 0x7C
+#define DMC_PHY_CON31 0x80
+#define DMC_PHY_CON32 0x84
+#define DMC_PHY_CON33 0x88
+#define DMC_PHY_CON34 0x8C
+#define DMC_PHY_CON35 0x90
+#define DMC_PHY_CON36 0x94
+#define DMC_PHY_CON37 0x98
+#define DMC_PHY_CON38 0x9C
+#define DMC_PHY_CON39 0xA0
+#define DMC_PHY_CON40 0xA4
+#define DMC_PHY_CON41 0xA8
+#define DMC_PHY_CON42 0xAC
+/*
+ * UART
+ */
+
+#define UART0_OFFSET 0x00000
+#define UART1_OFFSET 0x10000
+#define UART2_OFFSET 0x20000
+#define UART3_OFFSET 0x30000
+#define UART4_OFFSET 0x40000
+
+#if defined(CONFIG_SERIAL0)
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART0_OFFSET)
+#elif defined(CONFIG_SERIAL1)
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART1_OFFSET)
+#elif defined(CONFIG_SERIAL2)
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART2_OFFSET)
+#elif defined(CONFIG_SERIAL3)
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART3_OFFSET)
+#elif defined(CONFIG_SERIAL4)
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART4_OFFSET)
+#else
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART0_OFFSET)
+#endif
+
+#define ULCON_OFFSET 0x00
+#define UCON_OFFSET 0x04
+#define UFCON_OFFSET 0x08
+#define UMCON_OFFSET 0x0C
+#define UTRSTAT_OFFSET 0x10
+#define UERSTAT_OFFSET 0x14
+#define UFSTAT_OFFSET 0x18
+#define UMSTAT_OFFSET 0x1C
+#define UTXH_OFFSET 0x20
+#define URXH_OFFSET 0x24
+#define UBRDIV_OFFSET 0x28
+#define UDIVSLOT_OFFSET 0x2C
+#define UINTP_OFFSET 0x30
+#define UINTSP_OFFSET 0x34
+#define UINTM_OFFSET 0x38
+//#define UTRSTAT_TX_EMPTY BIT2
+//#define UTRSTAT_RX_READY BIT0
+#define UART_ERR_MASK 0xF
+
+/*
+ * HS MMC
+ */
+#define HSMMC_0_OFFSET 0x00000
+#define HSMMC_1_OFFSET 0x10000
+#define HSMMC_2_OFFSET 0x20000
+#define HSMMC_3_OFFSET 0x30000
+#define HSMMC_4_OFFSET 0x40000
+
+#define ELFIN_HSMMC_0_BASE (EXYNOS5250_HSMMC_BASE + HSMMC_0_OFFSET)
+#define ELFIN_HSMMC_1_BASE (EXYNOS5250_HSMMC_BASE + HSMMC_1_OFFSET)
+#define ELFIN_HSMMC_2_BASE (EXYNOS5250_HSMMC_BASE + HSMMC_2_OFFSET)
+#define ELFIN_HSMMC_3_BASE (EXYNOS5250_HSMMC_BASE + HSMMC_3_OFFSET)
+#define ELFIN_HSMMC_4_BASE (EXYNOS5250_HSMMC_BASE + HSMMC_4_OFFSET)
+
+#define HM_SYSAD (0x00)
+#define HM_BLKSIZE (0x04)
+#define HM_BLKCNT (0x06)
+#define HM_ARGUMENT (0x08)
+#define HM_TRNMOD (0x0c)
+#define HM_CMDREG (0x0e)
+#define HM_RSPREG0 (0x10)
+#define HM_RSPREG1 (0x14)
+#define HM_RSPREG2 (0x18)
+#define HM_RSPREG3 (0x1c)
+#define HM_BDATA (0x20)
+#define HM_PRNSTS (0x24)
+#define HM_HOSTCTL (0x28)
+#define HM_PWRCON (0x29)
+#define HM_BLKGAP (0x2a)
+#define HM_WAKCON (0x2b)
+#define HM_CLKCON (0x2c)
+#define HM_TIMEOUTCON (0x2e)
+#define HM_SWRST (0x2f)
+#define HM_NORINTSTS (0x30)
+#define HM_ERRINTSTS (0x32)
+#define HM_NORINTSTSEN (0x34)
+#define HM_ERRINTSTSEN (0x36)
+#define HM_NORINTSIGEN (0x38)
+#define HM_ERRINTSIGEN (0x3a)
+#define HM_ACMD12ERRSTS (0x3c)
+#define HM_CAPAREG (0x40)
+#define HM_MAXCURR (0x48)
+#define HM_CONTROL2 (0x80)
+#define HM_CONTROL3 (0x84)
+#define HM_CONTROL4 (0x8c)
+#define HM_HCVER (0xfe)
+
+/* PENDING BIT */
+#define BIT_EINT0 (0x1)
+#define BIT_EINT1 (0x1<<1)
+#define BIT_EINT2 (0x1<<2)
+#define BIT_EINT3 (0x1<<3)
+#define BIT_EINT4_7 (0x1<<4)
+#define BIT_EINT8_23 (0x1<<5)
+#define BIT_BAT_FLT (0x1<<7)
+#define BIT_TICK (0x1<<8)
+#define BIT_WDT (0x1<<9)
+#define BIT_TIMER0 (0x1<<10)
+#define BIT_TIMER1 (0x1<<11)
+#define BIT_TIMER2 (0x1<<12)
+#define BIT_TIMER3 (0x1<<13)
+#define BIT_TIMER4 (0x1<<14)
+#define BIT_UART2 (0x1<<15)
+#define BIT_LCD (0x1<<16)
+#define BIT_DMA0 (0x1<<17)
+#define BIT_DMA1 (0x1<<18)
+#define BIT_DMA2 (0x1<<19)
+#define BIT_DMA3 (0x1<<20)
+#define BIT_SDI (0x1<<21)
+#define BIT_SPI0 (0x1<<22)
+#define BIT_UART1 (0x1<<23)
+#define BIT_USBH (0x1<<26)
+#define BIT_IIC (0x1<<27)
+#define BIT_UART0 (0x1<<28)
+#define BIT_SPI1 (0x1<<29)
+#define BIT_RTC (0x1<<30)
+#define BIT_ADC (0x1<<31)
+#define BIT_ALLMSK (0xFFFFFFFF)
+
+#define PWMTIMER_BASE EXYNOS5250_PWMTIMER_BASE
+
+/*
+ * USBD3 SFR
+ */
+#define USBDEVICE3_LINK_BASE 0x12000000
+#define USBDEVICE3_PHYCTRL_BASE 0x12100000
+
+//==========================
+// Global Registers (Gxxxx)
+//==========================
+// Global Common Registers
+#define rGSBUSCFG0 (USBDEVICE3_LINK_BASE + 0xc100)
+#define rGSBUSCFG1 (USBDEVICE3_LINK_BASE + 0xc104)
+#define rGTXTHRCFG (USBDEVICE3_LINK_BASE + 0xc108)
+#define rGRXTHRCFG (USBDEVICE3_LINK_BASE + 0xc10c)
+#define rGCTL (USBDEVICE3_LINK_BASE + 0xc110)
+#define rGEVTEN (USBDEVICE3_LINK_BASE + 0xc114)
+#define rGSTS (USBDEVICE3_LINK_BASE + 0xc118)
+#define rGSNPSID (USBDEVICE3_LINK_BASE + 0xc120)
+#define rGGPIO (USBDEVICE3_LINK_BASE + 0xc124)
+#define rGUID (USBDEVICE3_LINK_BASE + 0xc128)
+#define rGUCTL (USBDEVICE3_LINK_BASE + 0xc12c)
+#define rGBUSERRADDR_LO (USBDEVICE3_LINK_BASE + 0xc130)
+#define rGBUSERRADDR_HI (USBDEVICE3_LINK_BASE + 0xc134)
+
+// Global Port to USB Instance Mapping Registers
+#define rGPRTBIMAP_LO (USBDEVICE3_LINK_BASE + 0xc138)
+#define rGPRTBIMAP_HI (USBDEVICE3_LINK_BASE + 0xc13c)
+#define rGPRTBIMAP_HS_LO (USBDEVICE3_LINK_BASE + 0xc180)
+#define rGPRTBIMAP_HS_HI (USBDEVICE3_LINK_BASE + 0xc184)
+#define rGPRTBIMAP_FS_LO (USBDEVICE3_LINK_BASE + 0xc188)
+#define rGPRTBIMAP_FS_HI (USBDEVICE3_LINK_BASE + 0xc18c)
+
+// Global Hardware Parameter Registers
+#define rGHWPARAMS0 (USBDEVICE3_LINK_BASE + 0xc140) // 0x20204000 @c510
+#define rGHWPARAMS1 (USBDEVICE3_LINK_BASE + 0xc144) // 0x0060c93b @c510
+#define rGHWPARAMS2 (USBDEVICE3_LINK_BASE + 0xc148) // 0x12345678 @c510
+#define rGHWPARAMS3 (USBDEVICE3_LINK_BASE + 0xc14c) // 0x10420085 @c510
+#define rGHWPARAMS4 (USBDEVICE3_LINK_BASE + 0xc150) // 0x48820004 @c510
+#define rGHWPARAMS5 (USBDEVICE3_LINK_BASE + 0xc154) // 0x04204108 @c510
+#define rGHWPARAMS6 (USBDEVICE3_LINK_BASE + 0xc158) // 0x04008020 @c510
+#define rGHWPARAMS7 (USBDEVICE3_LINK_BASE + 0xc15c) // 0x018516fe @c510
+#define rGHWPARAMS8 (USBDEVICE3_LINK_BASE + 0xc600) // 0x00000386 @c510
+
+// Global Debug Registers
+#define rGDBGFIFOSPACE (USBDEVICE3_LINK_BASE + 0xc160)
+#define rGDBGLTSSM (USBDEVICE3_LINK_BASE + 0xc164)
+#define rGDBGLSPMUX (USBDEVICE3_LINK_BASE + 0xc170)
+#define rGDBGLSP (USBDEVICE3_LINK_BASE + 0xc174)
+#define rGDBGEPINFO0 (USBDEVICE3_LINK_BASE + 0xc178)
+#define rGDBGEPINFO1 (USBDEVICE3_LINK_BASE + 0xc17c)
+
+// Global PHY Registers
+#define rGUSB2PHYCFG (USBDEVICE3_LINK_BASE + 0xc200)
+#define rGUSB2I2CCTL (USBDEVICE3_LINK_BASE + 0xc240)
+#define rGUSB2PHYACC (USBDEVICE3_LINK_BASE + 0xc280)
+#define rGUSB3PIPECTL (USBDEVICE3_LINK_BASE + 0xc2c0)
+
+// Global FIFO Size Registers (0 <= num <= 15 @510)
+#define rGTXFIFOSIZ(num) ((USBDEVICE3_LINK_BASE + 0xc300) + 0x04*num)
+#define rGRXFIFOSIZ0 (USBDEVICE3_LINK_BASE + 0xc380)
+
+// Global Event Buffer Registers (DWC_USB3_DEVICE_NUM_INT = 1 @C510, GHWPARAMS1[20:15])
+#define rGEVNTADR_LO0 (USBDEVICE3_LINK_BASE + 0xc400)
+#define rGEVNTADR_HI0 (USBDEVICE3_LINK_BASE + 0xc404)
+#define rGEVNTSIZ0 (USBDEVICE3_LINK_BASE + 0xc408)
+#define rGEVNTCOUNT0 (USBDEVICE3_LINK_BASE + 0xc40c)
+
+//==========================
+// Device Registers (Dxxxx)
+//==========================
+// Device Common Registers
+#define rDCFG (USBDEVICE3_LINK_BASE + 0xc700)
+#define rDCTL (USBDEVICE3_LINK_BASE + 0xc704)
+#define rDEVTEN (USBDEVICE3_LINK_BASE + 0xc708)
+#define rDSTS (USBDEVICE3_LINK_BASE + 0xc70c)
+#define rDGCMDPAR (USBDEVICE3_LINK_BASE + 0xc710)
+#define rDGCMD (USBDEVICE3_LINK_BASE + 0xc714)
+#define rDALEPENA (USBDEVICE3_LINK_BASE + 0xc720)
+
+// Device Endpoint Registers (0 <= ep <= 15)
+#define rDOEPCMDPAR2(ep) ((USBDEVICE3_LINK_BASE + 0xc800) + 0x20*ep)
+#define rDOEPCMDPAR1(ep) ((USBDEVICE3_LINK_BASE + 0xc804) + 0x20*ep)
+#define rDOEPCMDPAR0(ep) ((USBDEVICE3_LINK_BASE + 0xc808) + 0x20*ep)
+#define rDOEPCMD(ep) ((USBDEVICE3_LINK_BASE + 0xc80c) + 0x20*ep)
+
+#define rDIEPCMDPAR2(ep) ((USBDEVICE3_LINK_BASE + 0xc810) + 0x20*ep)
+#define rDIEPCMDPAR1(ep) ((USBDEVICE3_LINK_BASE + 0xc814) + 0x20*ep)
+#define rDIEPCMDPAR0(ep) ((USBDEVICE3_LINK_BASE + 0xc818) + 0x20*ep)
+#define rDIEPCMD(ep) ((USBDEVICE3_LINK_BASE + 0xc81c) + 0x20*ep)
+
+//==========================
+// USB DEVICE PHY CONTROL REGISTERS
+//==========================
+#define EXYNOS_PHY_LINKSYSTEM (USBDEVICE3_PHYCTRL_BASE + 0x04)
+#define EXYNOS_PHY_UTMI (USBDEVICE3_PHYCTRL_BASE + 0x08)
+#define EXYNOS_PHY_PIPE (USBDEVICE3_PHYCTRL_BASE + 0x0C)
+#define EXYNOS_PHY_CLKPWR (USBDEVICE3_PHYCTRL_BASE + 0x10)
+#define EXYNOS_PHY_REG0 (USBDEVICE3_PHYCTRL_BASE + 0x14)
+#define EXYNOS_PHY_REG1 (USBDEVICE3_PHYCTRL_BASE + 0x18)
+#define EXYNOS_PHY_PARAM0 (USBDEVICE3_PHYCTRL_BASE + 0x1C)
+#define EXYNOS_PHY_PARAM1 (USBDEVICE3_PHYCTRL_BASE + 0x20)
+#define EXYNOS_PHY_TERM (USBDEVICE3_PHYCTRL_BASE + 0x24)
+#define EXYNOS_PHY_TEST (USBDEVICE3_PHYCTRL_BASE + 0x28)
+#define EXYNOS_PHY_ADP (USBDEVICE3_PHYCTRL_BASE + 0x2C)
+#define EXYNOS_PHY_BATCHG (USBDEVICE3_PHYCTRL_BASE + 0x30)
+#define EXYNOS_PHY_RESUME (USBDEVICE3_PHYCTRL_BASE + 0x34)
+
+#endif /* _EXYNOS5250_CPU_H */
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Exynos5250_Evt1.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Exynos5250_Evt1.h
new file mode 100755
index 000000000..e229a1377
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform/Exynos5250_Evt1.h
@@ -0,0 +1,763 @@
+/*
+ * (C) Copyright 2012 Samsung Electronics Co. Ltd
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _EXYNOS5250_CPU_H
+#define _EXYNOS5250_CPU_H
+
+/* EXYNOS5250 */
+#define EXYNOS5250_PRO_ID 0x10000000
+#define EXYNOS5250_SYSREG_BASE 0x10050000
+#define EXYNOS5250_POWER_BASE 0x10040000
+#define EXYNOS5250_CLOCK_BASE 0x10010000
+#define EXYNOS5250_SROM_BASE 0x12250000
+#define EXYNOS5250_HSMMC_BASE 0x12200000
+#define EXYNOS5250_PWMTIMER_BASE 0x12DD0000
+#define EXYNOS5250_INF_REG_BASE 0x10040800
+#define EXYNOS5250_TZPC_BASE 0x10100000
+#define EXYNOS5250_UART_BASE 0x12C00000
+
+#define BIT0 0x00000001
+#define BIT1 0x00000002
+#define BIT2 0x00000004
+#define BIT3 0x00000008
+#define BIT4 0x00000010
+#define BIT5 0x00000020
+#define BIT6 0x00000040
+#define BIT7 0x00000080
+#define BIT8 0x00000100
+#define BIT9 0x00000200
+#define BIT10 0x00000400
+#define BIT11 0x00000800
+#define BIT12 0x00001000
+#define BIT13 0x00002000
+#define BIT14 0x00004000
+#define BIT15 0x00008000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+
+
+#define __REG(x) (*(unsigned int *)(x))
+
+/*
+ * CHIP ID
+ */
+#define CHIP_ID_BASE EXYNOS5250_PRO_ID
+#define PRO_ID_OFFSET 0x0
+#define PRO_ID __REG(CHIP_ID_BASE+PRO_ID_OFFSET)
+#define PRO_MAINREV ((PRO_ID >> 0x4) & 0x0f)
+#define PRO_SUBREV (PRO_ID & 0x0f)
+#define PRO_PKGINFO ((PRO_ID >> 0x8) & 0x0f)
+#define SCP_TYPE 0x0
+#define POP_TYPE 0x2
+
+/*
+ * SYSREG
+ */
+#define USB_CFG_OFFSET 0x230
+#define USB_CFG_REG (EXYNOS5250_SYSREG_BASE + USB_CFG_OFFSET)
+
+/*
+ * POWER
+ */
+#define ELFIN_POWER_BASE EXYNOS5250_POWER_BASE
+#define OMR_OFFSET 0x0
+#define SW_RST_REG_OFFSET 0x400
+#define SW_RST_REG __REG(EXYNOS5250_POWER_BASE + SW_RST_REG_OFFSET)
+
+#define FSYS_ARM_CONFIGURATION_OFFSET 0x2200
+#define EFNAND_PHY_CONTROL_OFFSET 0x070C
+#define SATA_PHY_CONTROL_OFFSET 0x0724
+
+#define INF_REG_BASE EXYNOS5250_INF_REG_BASE
+
+#define INF_REG0_OFFSET 0x00
+#define INF_REG1_OFFSET 0x04
+#define INF_REG2_OFFSET 0x08
+#define INF_REG3_OFFSET 0x0C
+#define INF_REG4_OFFSET 0x10
+#define INF_REG5_OFFSET 0x14
+#define INF_REG6_OFFSET 0x18
+#define INF_REG7_OFFSET 0x1C
+
+#define INF_REG0_REG __REG(INF_REG_BASE+INF_REG0_OFFSET)
+#define INF_REG1_REG __REG(INF_REG_BASE+INF_REG1_OFFSET)
+#define INF_REG2_REG __REG(INF_REG_BASE+INF_REG2_OFFSET)
+#define INF_REG3_REG __REG(INF_REG_BASE+INF_REG3_OFFSET)
+#define INF_REG4_REG __REG(INF_REG_BASE+INF_REG4_OFFSET)
+#define INF_REG5_REG __REG(INF_REG_BASE+INF_REG5_OFFSET)
+#define INF_REG6_REG __REG(INF_REG_BASE+INF_REG6_OFFSET)
+#define INF_REG7_REG __REG(INF_REG_BASE+INF_REG7_OFFSET)
+
+#define USB_DEVICE_PHY_CONTROL_OFFSET 0x0704
+#define USB_PHY_CONTROL_OFFSET 0x0708
+#define USB_DEVICE_PHY_CONTROL (EXYNOS5250_POWER_BASE+USB_DEVICE_PHY_CONTROL_OFFSET)
+#define USB_PHY_CONTROL (EXYNOS5250_POWER_BASE+USB_PHY_CONTROL_OFFSET)
+
+/* Define Mode */
+#define S5P_CHECK_SLEEP 0x00000BAD
+#define S5P_CHECK_DIDLE 0xBAD00000
+#define S5P_CHECK_LPA 0xABAD0000
+
+/*
+ * CLOCK
+ */
+#define ELFIN_CLOCK_BASE EXYNOS5250_CLOCK_BASE
+
+#define APLL_LOCK_OFFSET 0x00000
+#define APLL_CON0_OFFSET 0x00100
+#define APLL_CON1_OFFSET 0x00104
+#define CLK_SRC_CPU_OFFSET 0x00200
+#define CLK_MUX_STAT_CPU_OFFSET 0x00400
+#define CLK_DIV_CPU0_OFFSET 0x00500
+#define CLK_DIV_CPU1_OFFSET 0x00504
+#define CLK_DIV_STAT_CPU0_OFFSET 0x00600
+#define CLK_DIV_STAT_CPU1_OFFSET 0x00604
+#define CLK_GATE_SCLK_CPU_OFFSET 0x00800
+#define CLKOUT_CMU_CPU_OFFSET 0x00A00
+#define CLKOUT_CMU_CPU_DIV_STAT_OFFSET 0x00A04
+#define ARMCLK_STOPCTRL_OFFSET 0x01000
+#define PARITYFAIL_STATUS_OFFSET 0x01010
+#define PARITYFAIL_CLEAR_OFFSET 0x01014
+#define PWR_CTRL_OFFSET 0x01020
+#define PWR_CTRL2_OFFSET 0x01024
+#define APLL_CON0_L8_OFFSET 0x01100
+#define APLL_CON0_L7_OFFSET 0x01104
+#define APLL_CON0_L6_OFFSET 0x01108
+#define APLL_CON0_L5_OFFSET 0x0110C
+#define APLL_CON0_L4_OFFSET 0x01110
+#define APLL_CON0_L3_OFFSET 0x01114
+#define APLL_CON0_L2_OFFSET 0x01118
+#define APLL_CON0_L1_OFFSET 0x0111C
+#define IEM_CONTROL_OFFSET 0x01120
+#define APLL_CON1_L8_OFFSET 0x01200
+#define APLL_CON1_L7_OFFSET 0x01204
+#define APLL_CON1_L6_OFFSET 0x01208
+#define APLL_CON1_L5_OFFSET 0x0120C
+#define APLL_CON1_L4_OFFSET 0x01210
+#define APLL_CON1_L3_OFFSET 0x01214
+#define APLL_CON1_L2_OFFSET 0x01218
+#define APLL_CON1_L1_OFFSET 0x0121C
+#define CLKDIV_IEM_L8_OFFSET 0x01300
+#define CLKDIV_IEM_L7_OFFSET 0x01304
+#define CLKDIV_IEM_L6_OFFSET 0x01308
+#define CLKDIV_IEM_L5_OFFSET 0x0130C
+#define CLKDIV_IEM_L4_OFFSET 0x01310
+#define CLKDIV_IEM_L3_OFFSET 0x01314
+#define CLKDIV_IEM_L2_OFFSET 0x01318
+#define CLKDIV_IEM_L1_OFFSET 0x0131C
+#define MPLL_LOCK_OFFSET 0x04000
+#define MPLL_CON0_OFFSET 0x04100
+#define MPLL_CON1_OFFSET 0x04104
+#define CLK_SRC_CORE0_OFFSET 0x04200
+#define CLK_SRC_CORE1_OFFSET 0x04204
+#define CLK_SRC_MASK_CORE0_OFFSET 0x04300
+#define CLK_MUX_STAT_CORE1_OFFSET 0x04404
+#define CLK_DIV_CORE0_OFFSET 0x04500
+#define CLK_DIV_CORE1_OFFSET 0x04504
+#define CLK_DIV_SYSRGT_OFFSET 0x04508
+#define CLK_DIV_STAT_CORE0_OFFSET 0x04600
+#define CLK_DIV_STAT_CORE1_OFFSET 0x04604
+#define CLK_DIV_STAT_SYSRGT_OFFSET 0x04608
+#define CLK_GATE_IP_CORE_OFFSET 0x04900
+#define CLK_GATE_IP_SYSRGT_OFFSET 0x04904
+#define C2C_MONITOR_OFFSET 0x04910
+#define CLKOUT_CMU_CORE_OFFSET 0x04A00
+#define CLKOUT_CMU_CORE_DIV_STAT_OFFSET 0x04A04
+#define DCGIDX_MAP0_OFFSET 0x05000
+#define DCGIDX_MAP1_OFFSET 0x05004
+#define DCGIDX_MAP2_OFFSET 0x05008
+#define DCGPERF_MAP0_OFFSET 0x05020
+#define DCGPERF_MAP1_OFFSET 0x05024
+#define DVCIDX_MAP_OFFSET 0x05040
+#define FREQ_CPU_OFFSET 0x05060
+#define FREQ_DPM_OFFSET 0x05064
+#define DVSEMCLK_EN_OFFSET 0x05080
+#define MAXPERF_OFFSET 0x05084
+#define C2C_CONFIG_OFFSET 0x06000
+#define CLK_DIV_ACP_OFFSET 0x08500
+#define CLK_DIV_STAT_ACP_OFFSET 0x08600
+#define CLK_GATE_IP_ACP_OFFSET 0x08800
+#define CLK_DIV_SYSLFT_OFFSET 0x08900
+#define CLK_DIV_STAT_SYSLFT_OFFSET 0x08910
+#define CLK_GATE_IP_SYSLFT_OFFSET 0x08930
+#define CLKOUT_CMU_ACP_OFFSET 0x08A00
+#define CLKOUT_CMU_ACP_DIV_STAT_OFFSET 0x08A04
+#define UFMC_CONFIG_OFFSET 0x08A10
+#define CLK_DIV_ISP0_OFFSET 0x0C300
+#define CLK_DIV_ISP1_OFFSET 0x0C304
+#define CLK_DIV_ISP2_OFFSET 0x0C308
+#define CLK_DIV_STAT_ISP0_OFFSET 0x0C400
+#define CLK_DIV_STAT_ISP1_OFFSET 0x0C404
+#define CLK_DIV_STAT_ISP2_OFFSET 0x0C408
+#define CLK_GATE_IP_ISP0_OFFSET 0x0C800
+#define CLK_GATE_IP_ISP1_OFFSET 0x0C804
+#define CLK_GATE_SCLK_ISP_OFFSET 0x0C900
+#define MCUISP_PWR_CTRL_OFFSET 0x0C910
+#define CLKOUT_CMU_ISP_OFFSET 0x0CA00
+#define CLKOUT_CMU_ISP_DIV_STAT_OFFSET 0x0CA04
+#define CPLL_LOCK_OFFSET 0x10020
+#define EPLL_LOCK_OFFSET 0x10030
+#define VPLL_LOCK_OFFSET 0x10040
+#define GPLL_LOCK_OFFSET 0x10050
+#define CPLL_CON0_OFFSET 0x10120
+#define CPLL_CON1_OFFSET 0x10124
+#define EPLL_CON0_OFFSET 0x10130
+#define EPLL_CON1_OFFSET 0x10134
+#define EPLL_CON2_OFFSET 0x10138
+#define VPLL_CON0_OFFSET 0x10140
+#define VPLL_CON1_OFFSET 0x10144
+#define VPLL_CON2_OFFSET 0x10148
+#define GPLL_CON0_OFFSET 0x10150
+#define GPLL_CON1_OFFSET 0x10154
+#define CLK_SRC_TOP0_OFFSET 0x10210
+#define CLK_SRC_TOP1_OFFSET 0x10214
+#define CLK_SRC_TOP2_OFFSET 0x10218
+#define CLK_SRC_TOP3_OFFSET 0x1021C
+#define CLK_SRC_GSCL_OFFSET 0x10220
+#define CLK_SRC_DISP1_0_OFFSET 0x1022C
+#define CLK_SRC_MAU_OFFSET 0x10240
+#define CLK_SRC_FSYS_OFFSET 0x10244
+#define CLK_SRC_GEN_OFFSET 0x10248
+#define CLK_SRC_PERIC0_OFFSET 0x10250
+#define CLK_SRC_PERIC1_OFFSET 0x10254
+#define SCLK_SRC_ISP_OFFSET 0x10270
+#define CLK_SRC_MASK_TOP_OFFSET 0x10310
+#define CLK_SRC_MASK_GSCL_OFFSET 0x10320
+#define CLK_SRC_MASK_DISP1_0_OFFSET 0x1032C
+#define CLK_SRC_MASK_DISP1_1_OFFSET 0x10330
+#define CLK_SRC_MASK_MAU_OFFSET 0x10334
+#define CLK_SRC_MASK_FSYS_OFFSET 0x10340
+#define CLK_SRC_MASK_GEN_OFFSET 0x10344
+#define CLK_SRC_MASK_PERIC0_OFFSET 0x10350
+#define CLK_SRC_MASK_PERIC1_OFFSET 0x10354
+#define SCLK_SRC_MASK_ISP_OFFSET 0x10370
+#define CLK_MUX_STAT_TOP0_OFFSET 0x10410
+#define CLK_MUX_STAT_TOP1_OFFSET 0x10414
+#define CLK_MUX_STAT_TOP2_OFFSET 0x10418
+#define CLK_MUX_STAT_TOP3_OFFSET 0x1041C
+#define CLK_DIV_TOP0_OFFSET 0x10510
+#define CLK_DIV_TOP1_OFFSET 0x10514
+#define CLK_DIV_GSCL_OFFSET 0x10520
+#define CLK_DIV_DISP1_0_OFFSET 0x1052C
+#define CLK_DIV_GEN_OFFSET 0x1053C
+#define CLK_DIV_MAU_OFFSET 0x10544
+#define CLK_DIV_FSYS0_OFFSET 0x10548
+#define CLK_DIV_FSYS1_OFFSET 0x1054C
+#define CLK_DIV_FSYS2_OFFSET 0x10550
+#define CLK_DIV_PERIC0_OFFSET 0x10558
+#define CLK_DIV_PERIC1_OFFSET 0x1055C
+#define CLK_DIV_PERIC2_OFFSET 0x10560
+#define CLK_DIV_PERIC3_OFFSET 0x10564
+#define CLK_DIV_PERIC4_OFFSET 0x10568
+#define CLK_DIV_PERIC5_OFFSET 0x1056C
+#define SCLK_DIV_ISP_OFFSET 0x10580
+#define CLKDIV2_RATIO0_OFFSET 0x10590
+#define CLKDIV2_RATIO1_OFFSET 0x10594
+#define CLKDIV4_RATIO_OFFSET 0x105A0
+#define CLK_DIV_STAT_TOP0_OFFSET 0x10610
+#define CLK_DIV_STAT_TOP1_OFFSET 0x10614
+#define CLK_DIV_STAT_GSCL_OFFSET 0x10620
+#define CLK_DIV_STAT_DISP1_0_OFFSET 0x1062C
+#define CLK_DIV_STAT_GEN_OFFSET 0x1063C
+#define CLK_DIV_STAT_MAU_OFFSET 0x10644
+#define CLK_DIV_STAT_FSYS0_OFFSET 0x10648
+#define CLK_DIV_STAT_FSYS1_OFFSET 0x1064C
+#define CLK_DIV_STAT_FSYS2_OFFSET 0x10650
+#define CLK_DIV_STAT_PERIC0_OFFSET 0x10658
+#define CLK_DIV_STAT_PERIC1_OFFSET 0x1065C
+#define CLK_DIV_STAT_PERIC2_OFFSET 0x10660
+#define CLK_DIV_STAT_PERIC3_OFFSET 0x10664
+#define CLK_DIV_STAT_PERIC4_OFFSET 0x10668
+#define CLK_DIV_STAT_PERIC5_OFFSET 0x1066C
+#define SCLK_DIV_STAT_ISP_OFFSET 0x10680
+#define CLKDIV2_STAT0_OFFSET 0x10690
+#define CLKDIV2_STAT1_OFFSET 0x10694
+#define CLKDIV4_STAT_OFFSET 0x106A0
+#define CLK_GATE_TOP_SCLK_DISP1_OFFSET 0x10828
+#define CLK_GATE_TOP_SCLK_GEN_OFFSET 0x1082C
+#define CLK_GATE_TOP_SCLK_MAU_OFFSET 0x1083C
+#define CLK_GATE_TOP_SCLK_FSYS_OFFSET 0x10840
+#define CLK_GATE_TOP_SCLK_PERIC_OFFSET 0x10850
+#define CLK_GATE_TOP_SCLK_ISP_OFFSET 0x10870
+#define CLK_GATE_IP_GSCL_OFFSET 0x10920
+#define CLK_GATE_IP_DISP1_OFFSET 0x10928
+#define CLK_GATE_IP_MFC_OFFSET 0x1092C
+#define CLK_GATE_IP_G3D_OFFSET 0x10930
+#define CLK_GATE_IP_GEN_OFFSET 0x10934
+#define CLK_GATE_IP_FSYS_OFFSET 0x10944
+#define CLK_GATE_IP_PERIC_OFFSET 0x10950
+#define CLK_GATE_IP_PERIS_OFFSET 0x10960
+#define CLK_GATE_BLOCK_OFFSET 0x10980
+#define MCUIOP_PWR_CTRL_OFFSET 0x109A0
+#define CLKOUT_CMU_TOP_OFFSET 0x10A00
+#define CLKOUT_CMU_TOP_DIV_STAT_OFFSET 0x10A04
+#define CLK_SRC_LEX_OFFSET 0x14200
+#define CLK_MUX_STAT_LEX_OFFSET 0x14400
+#define CLK_DIV_LEX_OFFSET 0x14500
+#define CLK_DIV_STAT_LEX_OFFSET 0x14600
+#define CLK_GATE_IP_LEX_OFFSET 0x14800
+#define CLKOUT_CMU_LEX_OFFSET 0x14A00
+#define CLKOUT_CMU_LEX_DIV_STAT_OFFSET 0x14A04
+#define CLK_DIV_R0X_OFFSET 0x18500
+#define CLK_DIV_STAT_R0X_OFFSET 0x18600
+#define CLK_GATE_IP_R0X_OFFSET 0x18800
+#define CLKOUT_CMU_R0X_OFFSET 0x18A00
+#define CLKOUT_CMU_R0X_DIV_STAT_OFFSET 0x18A04
+#define CLK_DIV_R1X_OFFSET 0x1C500
+#define CLK_DIV_STAT_R1X_OFFSET 0x1C600
+#define CLK_GATE_IP_R1X_OFFSET 0x1C800
+#define CLKOUT_CMU_R1X_OFFSET 0x1CA00
+#define CLKOUT_CMU_R1X_DIV_STAT_OFFSET 0x1CA04
+#define BPLL_LOCK_OFFSET 0x20010
+#define BPLL_CON0_OFFSET 0x20110
+#define BPLL_CON1_OFFSET 0x20114
+#define CLK_SRC_CDREX_OFFSET 0x20200
+#define CLK_MUX_STAT_CDREX_OFFSET 0x20400
+#define CLK_DIV_CDREX_OFFSET 0x20500
+#define CLK_DIV_STAT_CDREX_OFFSET 0x20600
+#define CLK_GATE_IP_CDREX_OFFSET 0x20900
+#define DMC_FREQ_CTRL_OFFSET 0x20914
+#define DREX2_PAUSE_OFFSET 0x2091C
+#define CLKOUT_CMU_CDREX_OFFSET 0x20A00
+#define CLKOUT_CMU_CDREX_DIV_STAT_OFFSET 0x20A04
+#define LPDDR3PHY_CTRL 0x20A10
+#define LPDDR3PHY_CTRL_CON0 0x20A14
+#define LPDDR3PHY_CTRL_CON1 0x20A18
+#define LPDDR3PHY_CTRL_CON2 0x20A1C
+#define LPDDR3PHY_CTRL_CON3 0x20A20
+#define PLL_DIV2_SEL_OFFSET 0x20A24
+
+#define CLK_SRC_FSYS __REG(ELFIN_CLOCK_BASE+CLK_SRC_FSYS_OFFSET)
+#define CLK_DIV_FSYS0 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS0_OFFSET)
+#define CLK_DIV_FSYS1 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS1_OFFSET)
+#define CLK_DIV_FSYS2 __REG(ELFIN_CLOCK_BASE+CLK_DIV_FSYS2_OFFSET)
+#define APLL_CON0_REG __REG(ELFIN_CLOCK_BASE+APLL_CON0_OFFSET)
+#define MPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+MPLL_CON0_OFFSET)
+#define EPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+EPLL_CON0_OFFSET)
+#define VPLL_CON0_REG __REG(ELFIN_CLOCK_BASE+VPLL_CON0_OFFSET)
+
+/*
+ * TZPC
+ */
+#define TZPC0_OFFSET 0x00000
+#define TZPC1_OFFSET 0x10000
+#define TZPC2_OFFSET 0x20000
+#define TZPC3_OFFSET 0x30000
+#define TZPC4_OFFSET 0x40000
+#define TZPC5_OFFSET 0x50000
+#define TZPC6_OFFSET 0x60000
+#define TZPC7_OFFSET 0x70000
+#define TZPC8_OFFSET 0x80000
+#define TZPC9_OFFSET 0x90000
+
+#define ELFIN_TZPC0_BASE (EXYNOS5250_TZPC_BASE + TZPC0_OFFSET)
+#define ELFIN_TZPC1_BASE (EXYNOS5250_TZPC_BASE + TZPC1_OFFSET)
+#define ELFIN_TZPC2_BASE (EXYNOS5250_TZPC_BASE + TZPC2_OFFSET)
+#define ELFIN_TZPC3_BASE (EXYNOS5250_TZPC_BASE + TZPC3_OFFSET)
+#define ELFIN_TZPC4_BASE (EXYNOS5250_TZPC_BASE + TZPC4_OFFSET)
+#define ELFIN_TZPC5_BASE (EXYNOS5250_TZPC_BASE + TZPC5_OFFSET)
+#define ELFIN_TZPC6_BASE (EXYNOS5250_TZPC_BASE + TZPC6_OFFSET)
+#define ELFIN_TZPC7_BASE (EXYNOS5250_TZPC_BASE + TZPC7_OFFSET)
+#define ELFIN_TZPC8_BASE (EXYNOS5250_TZPC_BASE + TZPC8_OFFSET)
+#define ELFIN_TZPC9_BASE (EXYNOS5250_TZPC_BASE + TZPC9_OFFSET)
+
+#define TZPC_DECPROT0SET_OFFSET 0x804
+#define TZPC_DECPROT1SET_OFFSET 0x810
+#define TZPC_DECPROT2SET_OFFSET 0x81C
+#define TZPC_DECPROT3SET_OFFSET 0x828
+
+/*
+ * Memory controller
+ */
+#define ELFIN_SROM_BASE EXYNOS5250_SROM_BASE
+
+#define SROM_BW_REG __REG(ELFIN_SROM_BASE+0x0)
+#define SROM_BC0_REG __REG(ELFIN_SROM_BASE+0x4)
+#define SROM_BC1_REG __REG(ELFIN_SROM_BASE+0x8)
+#define SROM_BC2_REG __REG(ELFIN_SROM_BASE+0xC)
+#define SROM_BC3_REG __REG(ELFIN_SROM_BASE+0x10)
+
+/*
+ * SDRAM Controller
+ */
+
+/* DMC control register */
+#define DMC_CTRL_BASE 0x10DD0000
+
+#define DMC_CONCONTROL 0x00
+#define DMC_MEMCONTROL 0x04
+#define DMC_MEMCONFIG0 0x08
+#define DMC_MEMCONFIG1 0x0C
+#define DMC_DIRECTCMD 0x10
+#define DMC_PRECHCONFIG 0x14
+#define DMC_PHYCONTROL0 0x18
+#define DMC_PWRDNCONFIG 0x28
+#define DMC_TIMINGPZQ 0x2C
+#define DMC_TIMINGAREF 0x30
+#define DMC_TIMINGROW 0x34
+#define DMC_TIMINGDATA 0x38
+#define DMC_TIMINGPOWER 0x3C
+#define DMC_PHYSTATUS 0x40
+#define DMC_CHIPSTATUS_CH0 0x48
+#define DMC_CHIPSTATUS_CH1 0x4C
+#define DMC_MRSTATUS 0x54
+#define DMC_QOSCONTROL0 0x60
+#define DMC_QOSCONTROL1 0x68
+#define DMC_QOSCONTROL2 0x70
+#define DMC_QOSCONTROL3 0x78
+#define DMC_QOSCONTROL4 0x80
+#define DMC_QOSCONTROL5 0x88
+#define DMC_QOSCONTROL6 0x90
+#define DMC_QOSCONTROL7 0x98
+#define DMC_QOSCONTROL8 0xA0
+#define DMC_QOSCONTROL9 0xA8
+#define DMC_QOSCONTROL10 0xB0
+#define DMC_QOSCONTROL11 0xB8
+#define DMC_QOSCONTROL12 0xC0
+#define DMC_QOSCONTROL13 0xC8
+#define DMC_QOSCONTROL14 0xD0
+#define DMC_QOSCONTROL15 0xD8
+#define DMC_IVCONTROL 0xF0
+#define DMC_WRTRA_CONFIG 0xF4
+#define DMC_RDLVL_CONFIG 0xF8
+#define DMC_BRBRSVCONTROL 0x0100
+#define DMC_BRBRSVCONFIG 0x0104
+#define DMC_BRBQOSCONFIG 0x0108
+#define DMC_MEMBASECONFIG0 0x010C
+#define DMC_MEMBASECONFIG1 0x0110
+#define DMC_WRLVLCONFIG0 0x0120
+#define DMC_WRLVLCONFIG1 0x0124
+#define DMC_WRLVLSTATUS 0x0128
+#define DMC_PEREVCONTROL 0x0130
+#define DMC_PEREV0CONFIG 0x0134
+#define DMC_PEREV1CONFIG 0x0138
+#define DMC_PEREV2CONFIG 0x013C
+#define DMC_PEREV3CONFIG 0x0140
+#define DMC_CTRL_IO_RDATA_CH0 0x0150
+#define DMC_CTRL_IO_RDATA_CH1 0x0154
+#define DMC_CACAL_CONFIG0 0x0160
+#define DMC_CACAL_CONFIG1 0x0164
+#define DMC_CACAL_STATUS 0x0168
+#define DMC_PMNC_PPC 0xE000
+#define DMC_CNTENS_PPC 0xE010
+#define DMC_CNTENC_PPC 0xE020
+#define DMC_INTENS_PPC 0xE030
+#define DMC_INTENC_PPC 0xE040
+#define DMC_FLAG_PPC 0xE050
+#define DMC_CCNT_PPC 0xE100
+#define DMC_PMCNT0_PPC 0xE110
+#define DMC_PMCNT1_PPC 0xE120
+#define DMC_PMCNT2_PPC 0xE130
+#define DMC_PMCNT3_PPC 0xE140
+
+/* PHY Control Register */
+#define PHY0_CTRL_BASE 0x10C00000
+#define PHY1_CTRL_BASE 0x10C10000
+
+#define DMC_PHY_CON0 0x00
+#define DMC_PHY_CON1 0x04
+#define DMC_PHY_CON2 0x08
+#define DMC_PHY_CON3 0x0C
+#define DMC_PHY_CON4 0x10
+#define DMC_PHY_CON6 0x18
+#define DMC_PHY_CON8 0x20
+#define DMC_PHY_CON10 0x28
+#define DMC_PHY_CON11 0x2C
+#define DMC_PHY_CON12 0x30
+#define DMC_PHY_CON13 0x34
+#define DMC_PHY_CON14 0x38
+#define DMC_PHY_CON15 0x3C
+#define DMC_PHY_CON16 0x40
+#define DMC_PHY_CON17 0x48
+#define DMC_PHY_CON18 0x4C
+#define DMC_PHY_CON19 0x50
+#define DMC_PHY_CON20 0x54
+#define DMC_PHY_CON21 0x58
+#define DMC_PHY_CON22 0x5C
+#define DMC_PHY_CON23 0x60
+#define DMC_PHY_CON24 0x64
+#define DMC_PHY_CON25 0x68
+#define DMC_PHY_CON26 0x6C
+#define DMC_PHY_CON27 0x70
+#define DMC_PHY_CON28 0x74
+#define DMC_PHY_CON29 0x78
+#define DMC_PHY_CON30 0x7C
+#define DMC_PHY_CON31 0x80
+#define DMC_PHY_CON32 0x84
+#define DMC_PHY_CON33 0x88
+#define DMC_PHY_CON34 0x8C
+#define DMC_PHY_CON35 0x90
+#define DMC_PHY_CON36 0x94
+#define DMC_PHY_CON37 0x98
+#define DMC_PHY_CON38 0x9C
+#define DMC_PHY_CON39 0xA0
+#define DMC_PHY_CON40 0xA4
+#define DMC_PHY_CON41 0xA8
+#define DMC_PHY_CON42 0xAC
+
+
+/*
+ * FBM
+ */
+#define DDR_R1_FBM_BASE 0x10c30000
+#define DDR_R0_FBM_BASE 0x10dc0000
+
+#define FBM_MODESEL0 0x0
+#define FBM_THRESHOLDSEL0 0x40
+
+/*
+ * UART
+ */
+
+#define UART0_OFFSET 0x00000
+#define UART1_OFFSET 0x10000
+#define UART2_OFFSET 0x20000
+#define UART3_OFFSET 0x30000
+
+#if defined(CONFIG_SERIAL0)
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART0_OFFSET)
+#elif defined(CONFIG_SERIAL1)
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART1_OFFSET)
+#elif defined(CONFIG_SERIAL2)
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART2_OFFSET)
+#elif defined(CONFIG_SERIAL3)
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART3_OFFSET)
+#else
+#define UART_CONSOLE_BASE (EXYNOS5250_UART_BASE + UART0_OFFSET)
+#endif
+
+#define ULCON_OFFSET 0x00
+#define UCON_OFFSET 0x04
+#define UFCON_OFFSET 0x08
+#define UMCON_OFFSET 0x0C
+#define UTRSTAT_OFFSET 0x10
+#define UERSTAT_OFFSET 0x14
+#define UFSTAT_OFFSET 0x18
+#define UMSTAT_OFFSET 0x1C
+#define UTXH_OFFSET 0x20
+#define URXH_OFFSET 0x24
+#define UBRDIV_OFFSET 0x28
+#define UDIVSLOT_OFFSET 0x2C
+#define UINTP_OFFSET 0x30
+#define UINTSP_OFFSET 0x34
+#define UINTM_OFFSET 0x38
+//#define UTRSTAT_TX_EMPTY BIT2
+//#define UTRSTAT_RX_READY BIT0
+#define UART_ERR_MASK 0xF
+
+/*
+ * HS MMC
+ */
+#define HSMMC_0_OFFSET 0x00000
+#define HSMMC_1_OFFSET 0x10000
+#define HSMMC_2_OFFSET 0x20000
+#define HSMMC_3_OFFSET 0x30000
+
+#define ELFIN_HSMMC_0_BASE (EXYNOS5250_HSMMC_BASE + HSMMC_0_OFFSET)
+#define ELFIN_HSMMC_1_BASE (EXYNOS5250_HSMMC_BASE + HSMMC_1_OFFSET)
+#define ELFIN_HSMMC_2_BASE (EXYNOS5250_HSMMC_BASE + HSMMC_2_OFFSET)
+#define ELFIN_HSMMC_3_BASE (EXYNOS5250_HSMMC_BASE + HSMMC_3_OFFSET)
+
+#define HM_SYSAD (0x00)
+#define HM_BLKSIZE (0x04)
+#define HM_BLKCNT (0x06)
+#define HM_ARGUMENT (0x08)
+#define HM_TRNMOD (0x0c)
+#define HM_CMDREG (0x0e)
+#define HM_RSPREG0 (0x10)
+#define HM_RSPREG1 (0x14)
+#define HM_RSPREG2 (0x18)
+#define HM_RSPREG3 (0x1c)
+#define HM_BDATA (0x20)
+#define HM_PRNSTS (0x24)
+#define HM_HOSTCTL (0x28)
+#define HM_PWRCON (0x29)
+#define HM_BLKGAP (0x2a)
+#define HM_WAKCON (0x2b)
+#define HM_CLKCON (0x2c)
+#define HM_TIMEOUTCON (0x2e)
+#define HM_SWRST (0x2f)
+#define HM_NORINTSTS (0x30)
+#define HM_ERRINTSTS (0x32)
+#define HM_NORINTSTSEN (0x34)
+#define HM_ERRINTSTSEN (0x36)
+#define HM_NORINTSIGEN (0x38)
+#define HM_ERRINTSIGEN (0x3a)
+#define HM_ACMD12ERRSTS (0x3c)
+#define HM_CAPAREG (0x40)
+#define HM_MAXCURR (0x48)
+#define HM_CONTROL2 (0x80)
+#define HM_CONTROL3 (0x84)
+#define HM_CONTROL4 (0x8c)
+#define HM_HCVER (0xfe)
+
+/* PENDING BIT */
+#define BIT_EINT0 (0x1)
+#define BIT_EINT1 (0x1<<1)
+#define BIT_EINT2 (0x1<<2)
+#define BIT_EINT3 (0x1<<3)
+#define BIT_EINT4_7 (0x1<<4)
+#define BIT_EINT8_23 (0x1<<5)
+#define BIT_BAT_FLT (0x1<<7)
+#define BIT_TICK (0x1<<8)
+#define BIT_WDT (0x1<<9)
+#define BIT_TIMER0 (0x1<<10)
+#define BIT_TIMER1 (0x1<<11)
+#define BIT_TIMER2 (0x1<<12)
+#define BIT_TIMER3 (0x1<<13)
+#define BIT_TIMER4 (0x1<<14)
+#define BIT_UART2 (0x1<<15)
+#define BIT_LCD (0x1<<16)
+#define BIT_DMA0 (0x1<<17)
+#define BIT_DMA1 (0x1<<18)
+#define BIT_DMA2 (0x1<<19)
+#define BIT_DMA3 (0x1<<20)
+#define BIT_SDI (0x1<<21)
+#define BIT_SPI0 (0x1<<22)
+#define BIT_UART1 (0x1<<23)
+#define BIT_USBH (0x1<<26)
+#define BIT_IIC (0x1<<27)
+#define BIT_UART0 (0x1<<28)
+#define BIT_SPI1 (0x1<<29)
+#define BIT_RTC (0x1<<30)
+#define BIT_ADC (0x1<<31)
+#define BIT_ALLMSK (0xFFFFFFFF)
+
+#define PWMTIMER_BASE EXYNOS5250_PWMTIMER_BASE
+
+/*
+ * USBD3 SFR
+ */
+#define USBDEVICE3_LINK_BASE 0x12000000
+#define USBDEVICE3_PHYCTRL_BASE 0x12100000
+
+//==========================
+// Global Registers (Gxxxx)
+//==========================
+// Global Common Registers
+#define rGSBUSCFG0 (USBDEVICE3_LINK_BASE + 0xc100)
+#define rGSBUSCFG1 (USBDEVICE3_LINK_BASE + 0xc104)
+#define rGTXTHRCFG (USBDEVICE3_LINK_BASE + 0xc108)
+#define rGRXTHRCFG (USBDEVICE3_LINK_BASE + 0xc10c)
+#define rGCTL (USBDEVICE3_LINK_BASE + 0xc110)
+#define rGEVTEN (USBDEVICE3_LINK_BASE + 0xc114)
+#define rGSTS (USBDEVICE3_LINK_BASE + 0xc118)
+#define rGSNPSID (USBDEVICE3_LINK_BASE + 0xc120)
+#define rGGPIO (USBDEVICE3_LINK_BASE + 0xc124)
+#define rGUID (USBDEVICE3_LINK_BASE + 0xc128)
+#define rGUCTL (USBDEVICE3_LINK_BASE + 0xc12c)
+#define rGBUSERRADDR_LO (USBDEVICE3_LINK_BASE + 0xc130)
+#define rGBUSERRADDR_HI (USBDEVICE3_LINK_BASE + 0xc134)
+
+// Global Port to USB Instance Mapping Registers
+#define rGPRTBIMAP_LO (USBDEVICE3_LINK_BASE + 0xc138)
+#define rGPRTBIMAP_HI (USBDEVICE3_LINK_BASE + 0xc13c)
+#define rGPRTBIMAP_HS_LO (USBDEVICE3_LINK_BASE + 0xc180)
+#define rGPRTBIMAP_HS_HI (USBDEVICE3_LINK_BASE + 0xc184)
+#define rGPRTBIMAP_FS_LO (USBDEVICE3_LINK_BASE + 0xc188)
+#define rGPRTBIMAP_FS_HI (USBDEVICE3_LINK_BASE + 0xc18c)
+
+// Global Hardware Parameter Registers
+#define rGHWPARAMS0 (USBDEVICE3_LINK_BASE + 0xc140) // 0x20204000 @c510
+#define rGHWPARAMS1 (USBDEVICE3_LINK_BASE + 0xc144) // 0x0060c93b @c510
+#define rGHWPARAMS2 (USBDEVICE3_LINK_BASE + 0xc148) // 0x12345678 @c510
+#define rGHWPARAMS3 (USBDEVICE3_LINK_BASE + 0xc14c) // 0x10420085 @c510
+#define rGHWPARAMS4 (USBDEVICE3_LINK_BASE + 0xc150) // 0x48820004 @c510
+#define rGHWPARAMS5 (USBDEVICE3_LINK_BASE + 0xc154) // 0x04204108 @c510
+#define rGHWPARAMS6 (USBDEVICE3_LINK_BASE + 0xc158) // 0x04008020 @c510
+#define rGHWPARAMS7 (USBDEVICE3_LINK_BASE + 0xc15c) // 0x018516fe @c510
+#define rGHWPARAMS8 (USBDEVICE3_LINK_BASE + 0xc600) // 0x00000386 @c510
+
+// Global Debug Registers
+#define rGDBGFIFOSPACE (USBDEVICE3_LINK_BASE + 0xc160)
+#define rGDBGLTSSM (USBDEVICE3_LINK_BASE + 0xc164)
+#define rGDBGLSPMUX (USBDEVICE3_LINK_BASE + 0xc170)
+#define rGDBGLSP (USBDEVICE3_LINK_BASE + 0xc174)
+#define rGDBGEPINFO0 (USBDEVICE3_LINK_BASE + 0xc178)
+#define rGDBGEPINFO1 (USBDEVICE3_LINK_BASE + 0xc17c)
+
+// Global PHY Registers
+#define rGUSB2PHYCFG (USBDEVICE3_LINK_BASE + 0xc200)
+#define rGUSB2I2CCTL (USBDEVICE3_LINK_BASE + 0xc240)
+#define rGUSB2PHYACC (USBDEVICE3_LINK_BASE + 0xc280)
+#define rGUSB3PIPECTL (USBDEVICE3_LINK_BASE + 0xc2c0)
+
+// Global FIFO Size Registers (0 <= num <= 15 @510)
+#define rGTXFIFOSIZ(num) ((USBDEVICE3_LINK_BASE + 0xc300) + 0x04*num)
+#define rGRXFIFOSIZ0 (USBDEVICE3_LINK_BASE + 0xc380)
+
+// Global Event Buffer Registers (DWC_USB3_DEVICE_NUM_INT = 1 @C510, GHWPARAMS1[20:15])
+#define rGEVNTADR_LO0 (USBDEVICE3_LINK_BASE + 0xc400)
+#define rGEVNTADR_HI0 (USBDEVICE3_LINK_BASE + 0xc404)
+#define rGEVNTSIZ0 (USBDEVICE3_LINK_BASE + 0xc408)
+#define rGEVNTCOUNT0 (USBDEVICE3_LINK_BASE + 0xc40c)
+
+//==========================
+// Device Registers (Dxxxx)
+//==========================
+// Device Common Registers
+#define rDCFG (USBDEVICE3_LINK_BASE + 0xc700)
+#define rDCTL (USBDEVICE3_LINK_BASE + 0xc704)
+#define rDEVTEN (USBDEVICE3_LINK_BASE + 0xc708)
+#define rDSTS (USBDEVICE3_LINK_BASE + 0xc70c)
+#define rDGCMDPAR (USBDEVICE3_LINK_BASE + 0xc710)
+#define rDGCMD (USBDEVICE3_LINK_BASE + 0xc714)
+#define rDALEPENA (USBDEVICE3_LINK_BASE + 0xc720)
+
+// Device Endpoint Registers (0 <= ep <= 15)
+#define rDOEPCMDPAR2(ep) ((USBDEVICE3_LINK_BASE + 0xc800) + 0x20*ep)
+#define rDOEPCMDPAR1(ep) ((USBDEVICE3_LINK_BASE + 0xc804) + 0x20*ep)
+#define rDOEPCMDPAR0(ep) ((USBDEVICE3_LINK_BASE + 0xc808) + 0x20*ep)
+#define rDOEPCMD(ep) ((USBDEVICE3_LINK_BASE + 0xc80c) + 0x20*ep)
+
+#define rDIEPCMDPAR2(ep) ((USBDEVICE3_LINK_BASE + 0xc810) + 0x20*ep)
+#define rDIEPCMDPAR1(ep) ((USBDEVICE3_LINK_BASE + 0xc814) + 0x20*ep)
+#define rDIEPCMDPAR0(ep) ((USBDEVICE3_LINK_BASE + 0xc818) + 0x20*ep)
+#define rDIEPCMD(ep) ((USBDEVICE3_LINK_BASE + 0xc81c) + 0x20*ep)
+
+//==========================
+// USB DEVICE PHY CONTROL REGISTERS
+//==========================
+#define EXYNOS_PHY_LINKSYSTEM (USBDEVICE3_PHYCTRL_BASE + 0x04)
+#define EXYNOS_PHY_UTMI (USBDEVICE3_PHYCTRL_BASE + 0x08)
+#define EXYNOS_PHY_PIPE (USBDEVICE3_PHYCTRL_BASE + 0x0C)
+#define EXYNOS_PHY_CLKPWR (USBDEVICE3_PHYCTRL_BASE + 0x10)
+#define EXYNOS_PHY_REG0 (USBDEVICE3_PHYCTRL_BASE + 0x14)
+#define EXYNOS_PHY_REG1 (USBDEVICE3_PHYCTRL_BASE + 0x18)
+#define EXYNOS_PHY_PARAM0 (USBDEVICE3_PHYCTRL_BASE + 0x1C)
+#define EXYNOS_PHY_PARAM1 (USBDEVICE3_PHYCTRL_BASE + 0x20)
+#define EXYNOS_PHY_TERM (USBDEVICE3_PHYCTRL_BASE + 0x24)
+#define EXYNOS_PHY_TEST (USBDEVICE3_PHYCTRL_BASE + 0x28)
+#define EXYNOS_PHY_ADP (USBDEVICE3_PHYCTRL_BASE + 0x2C)
+#define EXYNOS_PHY_BATCHG (USBDEVICE3_PHYCTRL_BASE + 0x30)
+#define EXYNOS_PHY_RESUME (USBDEVICE3_PHYCTRL_BASE + 0x34)
+#define EXYNOS_PHY_LINK_PORT (USBDEVICE3_PHYCTRL_BASE + 0x44)
+
+/* USBD 2.0 SFR */
+#define USBOTG_LINK_BASE (0x12140000)
+#define USBOTG_PHY_BASE (0x12130000)
+
+#endif /* _EXYNOS5250_CPU_H */
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Protocol/ExynosGpio.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Protocol/ExynosGpio.h
new file mode 100644
index 000000000..35fe93bf6
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Protocol/ExynosGpio.h
@@ -0,0 +1,199 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ 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 __EXYNOS_GPIO_H__
+#define __EXYNOS_GPIO_H__
+
+//
+// Protocol interface structure
+//
+typedef struct _EXYNOS_GPIO EXYNOS_GPIO;
+
+//
+// Data Types
+//
+typedef UINTN EXYNOS_GPIO_PIN;
+
+#define GPIO(Port, Pin) ((EXYNOS_GPIO_PIN)(((Port) << (16)) | (Pin)))
+#define GPIO_PIN(x) ((EXYNOS_GPIO_PIN)(x) & (0xFFFF))
+#define GPIO_PORT(x) ((EXYNOS_GPIO_PIN)(x) >> (16))
+
+typedef enum {
+ GPIO_MODE_INPUT = 0x00,
+ GPIO_MODE_OUTPUT_0 = 0x0E,
+ GPIO_MODE_OUTPUT_1 = 0x0F,
+ GPIO_MODE_SPECIAL_FUNCTION_2 = 0x02,
+ GPIO_MODE_SPECIAL_FUNCTION_3 = 0x03,
+ GPIO_MODE_SPECIAL_FUNCTION_4 = 0x04,
+ GPIO_MODE_SPECIAL_FUNCTION_5 = 0x05,
+ GPIO_MODE_SPECIAL_FUNCTION_6 = 0x06,
+ GPIO_MODE_SPECIAL_FUNCTION_7 = 0x07
+} EXYNOS_GPIO_MODE;
+
+typedef enum {
+ GPIO_PULL_NONE,
+ GPIO_PULL_UP,
+ GPIO_PULL_DOWN
+} EXYNOS_GPIO_PULL;
+
+typedef enum {
+ GPIO_DRV_1X,
+ GPIO_DRV_2X,
+ GPIO_DRV_3X,
+ GPIO_DRV_4X
+} EXYNOS_GPIO_STRN;
+
+//
+// Function Prototypes
+//
+typedef
+EFI_STATUS
+(EFIAPI *EXYNOS_GPIO_GET) (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ OUT UINTN *Value
+ );
+/*++
+
+Routine Description:
+
+ Gets the state of a GPIO pin
+
+Arguments:
+
+ This - pointer to protocol
+ Gpio - which pin to read
+ Value - state of the pin
+
+Returns:
+
+ EFI_SUCCESS - GPIO state returned in Value
+
+--*/
+
+
+typedef
+EFI_STATUS
+(EFIAPI *EXYNOS_GPIO_SET) (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ IN EXYNOS_GPIO_MODE Mode
+ );
+/*++
+
+Routine Description:
+
+ Sets the state of a GPIO pin
+
+Arguments:
+
+ This - pointer to protocol
+ Gpio - which pin to modify
+ Mode - mode to set
+
+Returns:
+
+ EFI_SUCCESS - GPIO set as requested
+
+--*/
+
+
+typedef
+EFI_STATUS
+(EFIAPI *EXYNOS_GPIO_GET_MODE) (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ OUT EXYNOS_GPIO_MODE *Mode
+ );
+/*++
+
+Routine Description:
+
+ Gets the mode (function) of a GPIO pin
+
+Arguments:
+
+ This - pointer to protocol
+ Gpio - which pin
+ Mode - pointer to output mode value
+
+Returns:
+
+ EFI_SUCCESS - mode value retrieved
+
+--*/
+
+
+typedef
+EFI_STATUS
+(EFIAPI *EXYNOS_GPIO_SET_PULL) (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ IN EXYNOS_GPIO_PULL Direction
+ );
+/*++
+
+Routine Description:
+
+ Sets the pull-up / pull-down resistor of a GPIO pin
+
+Arguments:
+
+ This - pointer to protocol
+ Gpio - which pin
+ Direction - pull-up, pull-down, or none
+
+Returns:
+
+ EFI_SUCCESS - pin was set
+
+--*/
+
+typedef EFI_STATUS
+(EFIAPI *EXYNOS_GPIO_DRV) (
+ IN EXYNOS_GPIO *This,
+ IN EXYNOS_GPIO_PIN Gpio,
+ IN EXYNOS_GPIO_STRN Strength
+ );
+/*++
+
+Routine Description:
+
+ Sets the Driving strength resistor of a GPIO pin
+
+Arguments:
+
+ This - pointer to protocol
+ Gpio - which pin
+ Strength - 0=1x,1=2x,2=3x,3=4x
+
+Returns:
+
+ EFI_SUCCESS - pin was set
+
+--*/
+
+
+
+struct _EXYNOS_GPIO {
+ EXYNOS_GPIO_GET Get;
+ EXYNOS_GPIO_SET Set;
+ EXYNOS_GPIO_GET_MODE GetMode;
+ EXYNOS_GPIO_SET_PULL SetPull;
+ EXYNOS_GPIO_DRV SetStrength;
+};
+
+extern EFI_GUID gSamsungPlatformGpioProtocolGuid;
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Protocol/ExynosRng.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Protocol/ExynosRng.h
new file mode 100644
index 000000000..58376b530
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Protocol/ExynosRng.h
@@ -0,0 +1,52 @@
+/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ 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 __EXYNOS_RNG_H__
+#define __EXYNOS_RNG_H__
+
+//
+// Protocol interface structure
+//
+typedef struct _EFI_RNG_PROTOCOL EFI_RNG_PROTOCOL;
+
+/**
+ * Generates a pseudorandom byte stream of the specified size.
+ *
+ * If Output is NULL, then return FALSE.
+ *
+ * @param[out] Output Pointer to buffer to receive random value
+ * @param[in] Size Size of random bytes to generate
+ *
+ * @retval TRUE Pseudorandom byte stream generated successfully.
+ * @retval FALSE Pseudorandom number generator fails to generate due to lack of entropy.
+ *
+ **/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_RANDOM_BYTES) (
+ IN CONST EFI_RNG_PROTOCOL *This,
+ OUT UINT8 *Output,
+ IN UINTN Size
+ );
+
+///
+/// This protocol allows creating peudorandom random number using HW RNG engine.
+///
+struct _EFI_RNG_PROTOCOL {
+ EFI_RANDOM_BYTES RandomBytes;
+};
+
+extern EFI_GUID gSamsungPlatformRngProtocolGuid;
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.c
new file mode 100644
index 000000000..3dbee6de5
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.c
@@ -0,0 +1,51 @@
+/** @file
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <Base.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Platform/ArmPlatform.h>
+
+UINT32
+GpioBase (
+ IN UINTN Port
+ )
+{
+
+ ASSERT( ((Port >= GPA0) && (Port <= GPY6))
+ || ((Port >= GPX0) && (Port <= GPX3))
+ || ((Port >= GPE0) && (Port <= GPH1))
+ || ((Port >= GPV0) && (Port <= GPV4))
+ || (Port == GPZ));
+
+ /*decide which part of gpio is being requested. give the corresponding base address*/
+ if(Port >= 0x90) {
+ /* 0x0386_0000 */
+ Port -= 0x90;
+ return (PcdGet32(PcdGpioPart4Base) + (Port*DISTANCE_BTWN_PORTS));
+ }else if(Port >= 0x80) {
+ /* 0x10D1_0000 */
+ Port -= 0x80;
+ return (PcdGet32(PcdGpioPart3Base) + (Port*DISTANCE_BTWN_PORTS));
+ }else if(Port >= 0x70) {
+ /* 0x1340_0000 */
+ Port -= 0x70;
+ return (PcdGet32(PcdGpioPart2Base) + (Port*DISTANCE_BTWN_PORTS));
+ }else {
+ /* 0x1140_0000 */
+ return (PcdGet32(PcdGpioPart1Base) + (Port*DISTANCE_BTWN_PORTS));
+ }
+
+ ASSERT(FALSE); return 0;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.inf
new file mode 100644
index 000000000..f2b5f1dc2
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.inf
@@ -0,0 +1,42 @@
+#/** @file
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = ExynosLib
+ FILE_GUID = d035f5c2-1b92-4746-9f6c-5ff6202970df
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ExynosLib
+
+[Sources.common]
+ ExynosLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+
+[Protocols]
+
+[Guids]
+
+[Pcd]
+ gExynosPkgTokenSpaceGuid.PcdGpioPart1Base
+ gExynosPkgTokenSpaceGuid.PcdGpioPart2Base
+ gExynosPkgTokenSpaceGuid.PcdGpioPart3Base
+ gExynosPkgTokenSpaceGuid.PcdGpioPart4Base
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/GdbSerialLib/GdbSerialLib.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/GdbSerialLib/GdbSerialLib.c
new file mode 100644
index 000000000..db4eddf6e
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/GdbSerialLib/GdbSerialLib.c
@@ -0,0 +1,118 @@
+/** @file
+ Basic serial IO abstaction for GDB
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <Uefi.h>
+#include <Library/GdbSerialLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Platform/ArmPlatform.h>
+
+RETURN_STATUS
+EFIAPI
+GdbSerialLibConstructor (
+ VOID
+ )
+{
+ return GdbSerialInit (115200, 0, 8, 1);
+}
+
+RETURN_STATUS
+EFIAPI
+GdbSerialInit (
+ IN UINT64 BaudRate,
+ IN UINT8 Parity,
+ IN UINT8 DataBits,
+ IN UINT8 StopBits
+ )
+{
+ if ((Parity != 0) || (DataBits != 8) || (StopBits != 1)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ if (BaudRate != 115200) {
+ // Could add support for different Baud rates....
+ return RETURN_UNSUPPORTED;
+ }
+
+ UINT32 Base = PcdGet32 (PcdGdbUartBase);
+
+ // initialize baud rate generator to 115200 based on EB clock REFCLK24MHZ
+ MmioWrite32 (Base + UARTIBRD, UART_115200_IDIV);
+ MmioWrite32 (Base + UARTFBRD, UART_115200_FDIV);
+
+ // no parity, 1 stop, no fifo, 8 data bits
+ MmioWrite32 (Base + UARTLCR_H, 0x60);
+
+ // clear any pending errors
+ MmioWrite32 (Base + UARTECR, 0);
+
+ // enable tx, rx, and uart overall
+ MmioWrite32 (Base + UARTCR, 0x301);
+
+ return RETURN_SUCCESS;
+}
+
+BOOLEAN
+EFIAPI
+GdbIsCharAvailable (
+ VOID
+ )
+{
+ UINT32 FR = PcdGet32 (PcdGdbUartBase) + UTRSTAT_OFFSET;
+
+ if ((MmioRead32 (FR) & UART_RX_EMPTY_FLAG_MASK) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+CHAR8
+EFIAPI
+GdbGetChar (
+ VOID
+ )
+{
+ UINT32 FR = PcdGet32 (PcdGdbUartBase) + UTRSTAT_OFFSET;
+ UINT32 DR = PcdGet32 (PcdGdbUartBase) + URXH_OFFSET;
+
+ while ((MmioRead32 (FR) & UART_RX_EMPTY_FLAG_MASK) == 0);
+ return MmioRead8 (DR);
+}
+
+VOID
+EFIAPI
+GdbPutChar (
+ IN CHAR8 Char
+ )
+{
+ UINT32 FR = PcdGet32 (PcdGdbUartBase) + UTRSTAT_OFFSET;
+ UINT32 DR = PcdGet32 (PcdGdbUartBase) + UTXH_OFFSET;
+
+ while ((MmioRead32 (FR) & UART_TX_EMPTY_FLAG_MASK) != 0);
+ MmioWrite8 (DR, Char);
+ return;
+}
+
+VOID
+GdbPutString (
+ IN CHAR8 *String
+ )
+{
+ while (*String != '\0') {
+ GdbPutChar (*String);
+ String++;
+ }
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/GdbSerialLib/GdbSerialLib.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/GdbSerialLib/GdbSerialLib.inf
new file mode 100644
index 000000000..c557407e1
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/GdbSerialLib/GdbSerialLib.inf
@@ -0,0 +1,40 @@
+#/** @file
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = GdbSerialLib
+ FILE_GUID = E8EA1309-2F14-428f-ABE3-7016CE4B4305
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = GdbSerialLib
+
+ CONSTRUCTOR = GdbSerialLibConstructor
+
+
+[Sources.common]
+ GdbSerialLib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+
+[FixedPcd]
+ gExynosPkgTokenSpaceGuid.PcdGdbUartBase
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/RealTimeClockLib/RealTimeClockLib.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/RealTimeClockLib/RealTimeClockLib.c
new file mode 100644
index 000000000..2325a31b0
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/RealTimeClockLib/RealTimeClockLib.c
@@ -0,0 +1,363 @@
+/** @file
+ Implement EFI RealTimeClock runtime services via RTC Lib.
+
+ Currently this driver does not support runtime virtual calling.
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ 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 <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/RealTimeClockLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/RealTimeClock.h>
+#include <Guid/GlobalVariable.h>
+
+
+/*
+ * Kimoon added on 2011.12.08
+ */
+#include <Library/PcdLib.h>
+#include <Platform/ArmPlatform.h>
+
+#define RTC_YEAR_DATUM 2000
+
+unsigned bcd2bin(unsigned char val)
+{
+ return (val & 0x0f) + (val >> 4) * 10;
+}
+
+unsigned char bin2bcd(unsigned val)
+{
+ return ((val / 10) << 4) + val % 10;
+}
+
+/**
+ Returns the current time and date information, and the time-keeping capabilities
+ of the hardware platform.
+
+ @param Time A pointer to storage to receive a snapshot of the current time.
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
+ device's capabilities.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ )
+{
+ /*
+ * Kimoon added on 2011.12.08
+ */
+ UINT32 RtcBaseAddr;
+ BOOLEAN Retried = FALSE;
+
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __func__, __LINE__));
+
+ /*
+ * Check set time
+ */
+ if (Time == NULL)
+ goto cleanUp;
+
+ /*
+ * 1. Get RTC base address
+ */
+ RtcBaseAddr = PcdGet32(PcdRtcBase);
+
+ /*
+ * 2. Read registers
+ */
+RetryGetTime:
+ Time->Minute = MmioRead32(RtcBaseAddr + EXYNOS_BCDMIN);
+ Time->Hour = MmioRead32(RtcBaseAddr + EXYNOS_BCDHOUR);
+ Time->Day = MmioRead32(RtcBaseAddr + EXYNOS_BCDDAY);
+ Time->Month = MmioRead32(RtcBaseAddr + EXYNOS_BCDMON);
+ Time->Year = MmioRead32(RtcBaseAddr + EXYNOS_BCDYEAR);
+ Time->Second = MmioRead32(RtcBaseAddr + EXYNOS_BCDSEC);
+
+ /*
+ * 3. if second value is 0, try to read registers to escape errors.
+ */
+ if (Time->Second == 0 && !Retried) {
+ Retried = TRUE;
+ goto RetryGetTime;
+ }
+
+ /*
+ * 4. Change BCD values to real values.
+ */
+ Time->Second = bcd2bin(Time->Second);
+ Time->Minute = bcd2bin(Time->Minute);
+ Time->Hour = bcd2bin(Time->Hour);
+ Time->Day = bcd2bin(Time->Day);
+ Time->Month = bcd2bin(Time->Month);
+ Time->Year = bcd2bin(Time->Year) + RTC_YEAR_DATUM;
+
+ // Update the Capabilities info
+ if (Capabilities != NULL) {
+ // PL031 runs at frequency 1Hz
+ Capabilities->Resolution = 1;
+ // Accuracy in ppm multiplied by 1,000,000, e.g. for 50ppm set 50,000,000
+ Capabilities->Accuracy = 1000000;
+ // FALSE: Setting the time does not clear the values below the resolution level
+ Capabilities->SetsToZero = FALSE;
+ }
+
+
+ DEBUG((EFI_D_INFO, "--%a:%d (%d/%d/%d %d:%d:%d)\n",
+ __func__, __LINE__,
+ Time->Year, Time->Month, Time->Day, Time->Hour, Time->Minute, Time->Second));
+ return EFI_SUCCESS;
+
+cleanUp:
+ DEBUG((EFI_D_ERROR, "ERROR: %a:%d\n", __func__, __LINE__));
+ return EFI_DEVICE_ERROR;
+
+}
+
+
+/**
+ Sets the current local time and date information.
+
+ @param Time A pointer to the current time.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetTime (
+ IN EFI_TIME *Time
+ )
+{
+ /*
+ * Kimoon added on 2011.12.08
+ */
+ UINT32 RtcBaseAddr;
+
+ DEBUG((EFI_D_ERROR, "++%a:%d (%d/%d/%d %d:%d:%d)\n",
+ __func__, __LINE__,
+ Time->Year, Time->Month, Time->Day, Time->Hour, Time->Minute, Time->Second));
+
+ /*
+ * Check set time
+ */
+ if (Time == NULL)
+ goto cleanUp;
+
+ /*
+ * The RTC will only support a BCD year value of 0 - 99. The year datum is
+ * 2000, so any dates greater than 2099 will fail unless the datum is
+ * adjusted.
+ */
+ if ((Time->Year < RTC_YEAR_DATUM) || (Time->Year - RTC_YEAR_DATUM > 99)) {
+ DEBUG((EFI_D_ERROR, "RTC cannot support a year greater than %d or less than %d (value %d)\n",
+ (RTC_YEAR_DATUM + 99), RTC_YEAR_DATUM, Time->Year));
+ goto cleanUp;
+ }
+
+ /*
+ * 1. Get RTC base address
+ */
+ RtcBaseAddr = PcdGet32(PcdRtcBase);
+
+ /*
+ * 2. Set EXYNOS_RTCCON_RTCEN to Set BCD registers
+ * &= ~EXYNOS_RTCCON_RTCEN
+ * |= EXYNOS_RTCCON_RTCEN
+ */
+ MmioAndThenOr32(RtcBaseAddr + EXYNOS_RTCCON, \
+ ~EXYNOS_RTCCON_RTCEN, EXYNOS_RTCCON_RTCEN);
+
+ /*
+ * 3. Set BCD registers
+ */
+ MmioWrite32(RtcBaseAddr + EXYNOS_BCDSEC, bin2bcd(Time->Second));
+ MmioWrite32(RtcBaseAddr + EXYNOS_BCDMIN, bin2bcd(Time->Minute));
+ MmioWrite32(RtcBaseAddr + EXYNOS_BCDHOUR, bin2bcd(Time->Hour));
+ MmioWrite32(RtcBaseAddr + EXYNOS_BCDDAY, bin2bcd(Time->Day));
+ MmioWrite32(RtcBaseAddr + EXYNOS_BCDMON, bin2bcd(Time->Month));
+ MmioWrite32(RtcBaseAddr + EXYNOS_BCDYEAR, bin2bcd(Time->Year - RTC_YEAR_DATUM));
+
+ /*
+ * 4. Clear EXYNOS_RTCCON_RTCEN to close setting BCD registers
+ * &= ~EXYNOS_RTCCON_RTCEN
+ */
+ MmioAndThenOr32(RtcBaseAddr + EXYNOS_RTCCON, \
+ ~EXYNOS_RTCCON_RTCEN, (0<<0));
+
+ DEBUG((EFI_D_ERROR, "--%a:%d\n", __func__, __LINE__));
+ return EFI_SUCCESS;
+
+cleanUp:
+ DEBUG((EFI_D_ERROR, "ERROR: %a:%d\n", __func__, __LINE__));
+ return EFI_DEVICE_ERROR;
+
+}
+
+
+/**
+ Returns the current wakeup alarm clock setting.
+
+ @param Enabled Indicates if the alarm is currently enabled or disabled.
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.
+ @param Time The current alarm setting.
+
+ @retval EFI_SUCCESS The alarm settings were returned.
+ @retval EFI_INVALID_PARAMETER Any parameter is NULL.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ )
+{
+ // Not a required feature
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Sets the system wakeup alarm clock time.
+
+ @param Enabled Enable or disable the wakeup alarm.
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.
+
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
+ Enable is FALSE, then the wakeup alarm was disabled.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ )
+{
+ // Not a required feature
+ return EFI_UNSUPPORTED;
+}
+
+
+
+/**
+ This is the declaration of an EFI image entry point. This can be the entry point to an application
+ written to this specification, an EFI boot service driver, or an EFI runtime driver.
+
+ @param ImageHandle Handle that identifies the loaded image.
+ @param SystemTable System Table for this image.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRtcInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_TIME Time;
+
+ /*
+ * Kimoon added on 2011.12.08
+ */
+ DEBUG((EFI_D_INFO, "++%a:%d\n", __func__, __LINE__));
+
+ /*
+ * Mask RTC gating (bit clear)
+ */
+ MmioAndThenOr32((PcdGet32(PcdCmuBase) + CLK_GATE_IP_PERIR), \
+ ~CLK_RTC_OFFSET, CLK_RTC_MASK);
+
+ /*
+ * Unmask RTC gating (bit set)
+ */
+ MmioAndThenOr32((PcdGet32(PcdCmuBase) + CLK_GATE_IP_PERIR), \
+ ~CLK_RTC_OFFSET, CLK_RTC_UNMASK);
+
+
+ // Setup the setters and getters
+ gRT->GetTime = LibGetTime;
+ gRT->SetTime = LibSetTime;
+ gRT->GetWakeupTime = LibGetWakeupTime;
+ gRT->SetWakeupTime = LibSetWakeupTime;
+
+ Time.Second = 0;
+ Time.Minute = 0;
+ Time.Hour = 9;
+ Time.Day = 15;
+ Time.Month = 3;
+ Time.Year = 2012;
+
+ LibSetTime(&Time);
+
+ // Install the protocol
+ Handle = NULL;
+ gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiRealTimeClockArchProtocolGuid, NULL,
+ NULL
+ );
+
+ DEBUG((EFI_D_INFO, "--%a:%d\n", __func__, __LINE__));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+LibRtcVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // Only needed if you are going to support the OS calling RTC functions in virtual mode.
+ // You will need to call EfiConvertPointer (). To convert any stored physical addresses
+ // to virtual address. After the OS transistions to calling in virtual mode, all future
+ // runtime calls will be made in virtual mode.
+ //
+ return;
+}
+
+
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/RealTimeClockLib/RealTimeClockLib.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/RealTimeClockLib/RealTimeClockLib.inf
new file mode 100644
index 000000000..78c6937a6
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/RealTimeClockLib/RealTimeClockLib.inf
@@ -0,0 +1,42 @@
+#/** @file
+# Memory Status Code Library for UEFI drivers
+#
+# Lib to provide memory journal status code reporting Routines
+# Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+#
+# 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 = TemplateRealTimeClockLib
+ FILE_GUID = B661E02D-A90B-42AB-A5F9-CF841AAA43D9
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RealTimeClockLib
+
+
+[Sources.common]
+ RealTimeClockLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+
+[LibraryClasses]
+ IoLib
+ UefiLib
+ DebugLib
+
+[Pcd.common]
+ gExynosPkgTokenSpaceGuid.PcdRtcBase
+ gExynosPkgTokenSpaceGuid.PcdCmuBase
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ResetSystemLib/ResetSystemLib.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ResetSystemLib/ResetSystemLib.c
new file mode 100644
index 000000000..295a42546
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ResetSystemLib/ResetSystemLib.c
@@ -0,0 +1,241 @@
+/** @file
+ Template library implementation to support ResetSystem Runtime call.
+
+ Fill in the templates with what ever makes you system reset.
+
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <PiDxe.h>
+
+#include <Library/UefiRuntimeLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EfiResetSystemLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Platform/ArmPlatform.h>
+
+#include <Guid/EventGroup.h>
+
+
+/* Round off to 4KB pages */
+#define ROUND_TO_PAGE(x) (x & 0xfffff000)
+
+
+UINT32 gPmuBaseAddress = 0;
+EFI_EVENT VirtualAddressChangeEvent = NULL;
+
+VOID DestroyExynosMemMap(VOID);
+typedef VOID (EFIAPI *ptrImageStart)(VOID);
+
+/**
+ Virtual address change notification call back. It converts global pointer
+ to virtual address.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context Pointer to the notification function's context, which is
+ always zero in current implementation.
+**/
+VOID
+EFIAPI
+VirtualAddressChangeCallBack (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gRT->ConvertPointer(0, (VOID**)&gPmuBaseAddress);
+ gRT->ConvertPointer(0, (VOID**)&gRT);
+}
+
+
+VOID
+DestroyExynosMemMap (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN MemoryMapSize;
+ EFI_MEMORY_DESCRIPTOR *MemoryMap;
+ UINTN MapKey;
+ UINTN DescriptorSize;
+ UINTN DescriptorVersion;
+ UINTN Pages;
+
+ MemoryMap = NULL;
+ MemoryMapSize = 0;
+ do {
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+
+ Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
+ MemoryMap = AllocatePages (Pages);
+
+ //
+ // Get System MemoryMap
+ //
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ // Don't do anything between the GetMemoryMap() and ExitBootServices()
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->ExitBootServices (gImageHandle, MapKey);
+ if (EFI_ERROR (Status)) {
+ FreePages (MemoryMap, Pages);
+ MemoryMap = NULL;
+ MemoryMapSize = 0;
+ }
+ }
+ }
+ } while (EFI_ERROR (Status));
+
+ //Clean and invalidate caches.
+ WriteBackInvalidateDataCache();
+ InvalidateInstructionCache();
+
+ //Turning off Caches and MMU
+ ArmDisableDataCache ();
+ ArmDisableInstructionCache ();
+ ArmDisableMmu ();
+}
+
+
+
+/**
+ Resets the entire platform.
+
+ @param ResetType The type of reset to perform.
+ @param ResetStatus The status code for the reset.
+ @param DataSize The size, in bytes, of WatchdogData.
+ @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
+ EfiResetShutdown the data buffer starts with a Null-terminated
+ Unicode string, optionally followed by additional binary data.
+
+**/
+EFI_STATUS
+EFIAPI
+LibResetSystem (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN CHAR16 *ResetData OPTIONAL
+ )
+{
+ volatile UINT32 count = 0;
+
+ if (EfiAtRuntime())
+ {
+ while (count < 0x1000000)
+ {
+ count++;
+ }
+ }
+
+ switch (ResetType) {
+ case EfiResetShutdown:
+ case EfiResetCold:
+ case EfiResetWarm:
+ //Perform warm reset of the system by jumping to the begining of the FV
+ //((ptrImageStart)PcdGet32(PcdFvBaseAddress))();
+ //break;
+ default:
+ if(EfiAtRuntime () == 0)
+ {
+ DestroyExynosMemMap();
+ }
+
+ /* Perform cold reset of the system - should not return */
+ MmioWrite32 ((gPmuBaseAddress + SWRESET_OFFSET), 0x01);
+ while ((MmioRead32(gPmuBaseAddress + SWRESET_OFFSET)) != 0x1);
+ break;
+ }
+
+ // If the reset didn't work, return an error.
+ ASSERT (FALSE);
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Initialize any infrastructure required for LibResetSystem () to function.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+LibInitializeResetSystem (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR PmuMemoryDescriptor;
+
+ gPmuBaseAddress = PcdGet32(PcdPmuBase);
+
+ /*
+ * Get the GCD Memory Descriptor specified by WdtBaseAddress page boundary
+ */
+ Status = gDS->GetMemorySpaceDescriptor (ROUND_TO_PAGE(gPmuBaseAddress),
+ &PmuMemoryDescriptor);
+ ASSERT_EFI_ERROR (Status);
+
+ /*
+ * Mark the 4KB region as EFI_RUNTIME_MEMORY so the OS
+ * will allocate a virtual address range.
+ */
+ Status = gDS->SetMemorySpaceAttributes (
+ ROUND_TO_PAGE(gPmuBaseAddress),
+ EFI_PAGE_SIZE,
+ PmuMemoryDescriptor.Attributes | EFI_MEMORY_RUNTIME);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ VirtualAddressChangeCallBack,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &VirtualAddressChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+
+
+ return EFI_SUCCESS;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ResetSystemLib/ResetSystemLib.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ResetSystemLib/ResetSystemLib.inf
new file mode 100644
index 000000000..314078c32
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ResetSystemLib/ResetSystemLib.inf
@@ -0,0 +1,52 @@
+#/** @file
+# Reset System lib to make it easy to port new platforms
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+#
+# 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 = ResetSystemLib
+ FILE_GUID = CEFFA65C-B568-453e-9E11-B81AE683D035
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = EfiResetSystemLib
+
+
+[Sources.common]
+ ResetSystemLib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+
+[LibraryClasses]
+ DxeServicesTableLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiRuntimeLib
+ DebugLib
+ BaseLib
+ IoLib
+ MemoryAllocationLib
+ ArmLib
+ CacheMaintenanceLib
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gExynosPkgTokenSpaceGuid.PcdPmuBase
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/SerialPortLib/SerialPortLib_Evt1.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/SerialPortLib/SerialPortLib_Evt1.c
new file mode 100755
index 000000000..1e5791bd8
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/SerialPortLib/SerialPortLib_Evt1.c
@@ -0,0 +1,159 @@
+/** @file
+ Serial I/O Port library functions with no library constructor/destructor
+
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <Include/Uefi.h>
+#include <Library/SerialPortLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Platform/ArmPlatform.h>
+#include <Library/DebugLib.h>
+
+/*
+
+ Programmed hardware of Serial port.
+ Irrespective of the previous settings Initialize it to current requirement
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ UINT32 UARTConsoleBase;
+ UINT32 Tmp;
+
+ UARTConsoleBase=PcdGet32(PcdConsoleUartBase);
+
+ // GPIO
+ MmioWrite32(0x11400000, 0x00002222);
+ MmioWrite32(0x11400020, 0x222222);
+ MmioWrite32(0x11400160, 0x2222);
+
+ // CMU
+ Tmp = MmioRead32(0x10020250);
+// DEBUG ((EFI_D_ERROR, "%X \n", Tmp));
+
+ Tmp &= ~((0xF << 16) + (0xF << 12) + (0xF << 8) + (0xF << 4) + (0xF << 0));
+ Tmp |= ((0x6 << 16) + (0x6 << 12) + (0x6 << 8) + (0x6 << 4) + (0x6 << 0));
+ MmioWrite32 (0x10020250, Tmp);
+
+ Tmp = MmioRead32(0x10020558);
+ Tmp &= ~((0xF << 16) + (0xF << 12) + (0xF << 8) + (0xF << 4) + (0xF << 0));
+ Tmp |= ((0x7 << 16) + (0x7 << 12) + (0x7 << 8) + (0x7 << 4) + (0x7 << 0));
+ MmioWrite32 (0x10020558, Tmp);
+
+ // UART
+ MmioWrite32(UARTConsoleBase, 0x3);
+ MmioWrite32(UARTConsoleBase+0x4, 0x3C5);
+ MmioWrite32(UARTConsoleBase+0x8, 0x111);
+ MmioWrite32(UARTConsoleBase+0x28, 0x23);
+ MmioWrite32(UARTConsoleBase+0x2C, 0x2);
+/*
+ MmioWrite32(UARTConsoleBase+0x20, 0x4F);
+ MmioWrite32(UARTConsoleBase+0x20, 0x4F);
+ MmioWrite32(UARTConsoleBase+0x20, 0x4F);
+ MmioWrite32(UARTConsoleBase+0x20, 0x4F);
+ MmioWrite32(UARTConsoleBase+0x20, 0x4F);
+ MmioWrite32(UARTConsoleBase+0x20, 0x4F);
+*/
+ // For WindDebug Uart initialization
+ UARTConsoleBase=PcdGet32(PcdWinDebugUartBase);
+ MmioWrite32(UARTConsoleBase, 0x3);
+ MmioWrite32(UARTConsoleBase+0x4, 0x3C5);
+ MmioWrite32(UARTConsoleBase+0x8, 0x111);
+ MmioWrite32(UARTConsoleBase+0x28, 0x35);
+ MmioWrite32(UARTConsoleBase+0x2C, 0x4);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write data to serial device.
+
+ @param Buffer Point of data buffer which need to be writed.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Write data failed.
+ @retval !0 Actual number of bytes writed to serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+ IN UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ UINTN Count;
+ UINT32 UARTConsoleBase;
+
+ UARTConsoleBase=PcdGet32(PcdConsoleUartBase);
+ for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
+ while ((MmioRead32 (UARTConsoleBase + UTRSTAT_OFFSET) & UART_TX_EMPTY_FLAG_MASK) == 0);
+ MmioWrite8 (UARTConsoleBase + UTXH_OFFSET, *Buffer);
+ }
+
+ return NumberOfBytes;
+}
+
+/**
+ Read data from serial device and save the datas in buffer.
+
+ @param Buffer Point of data buffer which need to be writed.
+ @param NumberOfBytes Number of output bytes which are cached in Buffer.
+
+ @retval 0 Read data failed.
+ @retval !0 Aactual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+ OUT UINT8 *Buffer,
+ IN UINTN NumberOfBytes
+)
+{
+ UINTN Count;
+ UINT32 UARTConsoleBase;
+
+ UARTConsoleBase=PcdGet32(PcdConsoleUartBase);
+ for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
+ while ((MmioRead32 (UARTConsoleBase + UTRSTAT_OFFSET) & UART_RX_EMPTY_FLAG_MASK) == 0);
+ *Buffer = MmioRead8 (UARTConsoleBase + URXH_OFFSET);
+ }
+
+ return NumberOfBytes;
+}
+
+/**
+ Check to see if any data is avaiable to be read from the debug device.
+
+ @retval EFI_SUCCESS At least one byte of data is avaiable to be read
+ @retval EFI_NOT_READY No data is avaiable to be read
+ @retval EFI_DEVICE_ERROR The serial device is not functioning properly
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+ VOID
+ )
+{
+ UINT32 UARTConsoleBase;
+ UARTConsoleBase=PcdGet32(PcdConsoleUartBase);
+
+ return ((MmioRead32 (UARTConsoleBase + UTRSTAT_OFFSET) & UART_RX_EMPTY_FLAG_MASK) != 0);
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/SerialPortLib/SerialPortLib_Evt1.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/SerialPortLib/SerialPortLib_Evt1.inf
new file mode 100755
index 000000000..de89bad23
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/SerialPortLib/SerialPortLib_Evt1.inf
@@ -0,0 +1,38 @@
+#/** @file
+#
+# Component discription file for NorFlashDxe module
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = SerialPortLib
+ FILE_GUID = 8ecefc8f-a2c4-4091-b80f-20f7aeb0567f
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib
+
+[Sources.common]
+ SerialPortLib_Evt1.c
+
+[LibraryClasses]
+ IoLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ # ArmPlatformPkg/ArmPlatformPkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+
+[FixedPcd]
+ gExynosPkgTokenSpaceGuid.PcdConsoleUartBase
+ gExynosPkgTokenSpaceGuid.PcdWinDebugUartBase
+ gExynosPkgTokenSpaceGuid.PcdCmuBase
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/TimerLib/TimerLib.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/TimerLib/TimerLib.c
new file mode 100644
index 000000000..f828b53fa
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/TimerLib/TimerLib.c
@@ -0,0 +1,287 @@
+/** @file
+
+ Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+
+ 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 <Base.h>
+
+#include <Library/BaseLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Platform/ArmPlatform.h>
+#include <Library/ExynosTimerLib.h>
+
+
+// Setup SP810's Timer2 for managing delay functions. And Timer3 for Performance counter
+// Note: ArmVE's Timer0 and Timer1 are used by TimerDxe.
+RETURN_STATUS
+EFIAPI
+TimerConstructor (
+ VOID
+ )
+{
+ UINT32 PWMTimerBase;
+ UINT32 Tmp;
+
+ PWMTimerBase = PcdGet32(PcdPWMTimerBase);
+
+/**
+ This function is for initializing for PWM Timer
+ Timer 2 = > Delay Counter
+ Timer 3 = > Performance Counter
+**/
+// PWM Input Clock(ACLK_100) is 100 Mhz so We need to prescale about 1Mhz to make udelay function
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCFG0_OFFSET);
+ Tmp &= ~(0xFF << 8);
+ Tmp |= (0x63 << 8);
+ MmioWrite32 ((PWMTimerBase + PWM_TCFG0_OFFSET), Tmp);
+ MmioWrite32 ((PWMTimerBase + PWM_TCFG1_OFFSET), 0x0);
+
+// PWM Timer INT disable
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TINT_CSTAT_OFFSET);
+ Tmp &= ~(0x3 << 2);
+ MmioWrite32 ((PWMTimerBase + PWM_TINT_CSTAT_OFFSET), Tmp);
+
+// PWM Timer 2,3 make to stop
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCON_OFFSET);
+ Tmp &= ~(0xFF << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+// PWM Timer 3 used by Free running counter with Auto re-load mode
+ MmioWrite32 ((PWMTimerBase + PWM_TCNTB3_OFFSET), 0xFFFFFFFF);
+// Set and Clear PWM Manually update for Timer 3
+ Tmp |= (0x2 << 16);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ Tmp &= ~(0x2 << 16);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+// Set Auto re-load and start Timer
+ Tmp |= (0x9 << 16);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+ DEBUG ((EFI_D_ERROR, "Timer 2,3 Enabled\n"));
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Stalls the CPU for at least the given number of microseconds.
+
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+ @param MicroSeconds The minimum number of microseconds to delay.
+
+ @return The value of MicroSeconds inputted.
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+ IN UINTN MicroSeconds
+ )
+{
+ UINT32 Tmp;
+ UINT32 PWMTimerBase;
+ UINT32 i = 0;
+
+ PWMTimerBase=PcdGet32(PcdPWMTimerBase);
+ /* load the timer count register */
+ MmioWrite32 ((PWMTimerBase + PWM_TCNTB2_OFFSET), MicroSeconds);
+
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCON_OFFSET);
+
+ /* Stop Timer 2 */
+ Tmp &= ~(0xF << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ /* Set and Clear for Manually Update Counter Buffer */
+ Tmp |= (0x2 << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ Tmp &= ~(0x2 << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ /* Start Timer 2 */
+ Tmp |= (0x1 << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+ /*
+ * When ARM clock is 1GHz, 1 clock time is 1us.
+ * Simply counting, CounterValue maybe can't be updated within 10 instruction execution.
+ * So it is needed to check CounterValue register a couple of times
+ */
+ do {
+ /* Doesn't need to check if timer starts */
+ if ((MmioRead32 (PWMTimerBase + PWM_TCNTO2_OFFSET)) != 0)
+ break;
+ /* Supports meaningful delay */
+ if (MicroSeconds < 10000)
+ break;
+ /* Timer should start Within this time */
+ if (i++ > 20)
+ break;
+ } while ((MmioRead32 (PWMTimerBase + PWM_TCNTO2_OFFSET)) == 0);
+
+ /* Wait for requested delay time */
+ while (MmioRead32 (PWMTimerBase + PWM_TCNTO2_OFFSET) > 0) {
+ ;
+ }
+
+ /* Stop Timer 2 */
+ Tmp &= ~(0xF << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+ return MicroSeconds;
+}
+
+/**
+ Stalls the CPU for at least the given number of nanoseconds.
+
+ Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+ @param NanoSeconds The minimum number of nanoseconds to delay.
+
+ @return The value of NanoSeconds inputted.
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+ IN UINTN NanoSeconds
+ )
+{
+ UINT32 MicroSeconds;
+ UINT32 Tmp;
+ UINT32 PWMTimerBase;
+
+ PWMTimerBase=PcdGet32(PcdPWMTimerBase);
+
+ // Round up to 1us Tick Number
+ MicroSeconds = (UINT32)NanoSeconds / 1000;
+ MicroSeconds += ((UINT32)NanoSeconds % 1000) == 0 ? 0 : 1;
+ // load the timer count register
+ MmioWrite32 ((PWMTimerBase + PWM_TCNTB2_OFFSET), MicroSeconds);
+
+ Tmp = MmioRead32 (PWMTimerBase + PWM_TCON_OFFSET);
+ //Stop Timer 2
+ Tmp &= ~(0xF << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ //Set and Clear for Manually Update Counter Buffer
+ Tmp |= (0x2 << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ Tmp &= ~(0x2 << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+ //Start Timer 2
+ Tmp |= (0x1 << 12);
+ MmioWrite32 ((PWMTimerBase + PWM_TCON_OFFSET), Tmp);
+
+ //Wait for requested delay time
+ while (MmioRead32 (PWMTimerBase + PWM_TCNTO2_OFFSET) > 0) {
+ ;
+ }
+
+ return NanoSeconds;
+}
+
+/**
+ Retrieves the current value of a 64-bit free running performance counter.
+
+ The counter can either count up by 1 or count down by 1. If the physical
+ performance counter counts by a larger increment, then the counter values
+ must be translated. The properties of the counter can be retrieved from
+ GetPerformanceCounterProperties().
+
+ @return The current value of the free running performance counter.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounter (
+ VOID
+ )
+{
+ UINT32 PWMTimerBase;
+
+ PWMTimerBase=PcdGet32(PcdPWMTimerBase);
+ // Free running 64-bit/32-bit counter is needed here.
+ // Don't think we need this to boot, just to do performance profile
+ // ASSERT (FALSE);
+ UINT32 val = MmioRead32 (PWMTimerBase + PWM_TCNTO3_OFFSET);
+
+ ASSERT(val > 0);
+
+ return (UINT64)val;
+}
+
+
+/**
+ Retrieves the 64-bit frequency in Hz and the range of performance counter
+ values.
+
+ If StartValue is not NULL, then the value that the performance counter starts
+ with immediately after is it rolls over is returned in StartValue. If
+ EndValue is not NULL, then the value that the performance counter end with
+ immediately before it rolls over is returned in EndValue. The 64-bit
+ frequency of the performance counter in Hz is always returned. If StartValue
+ is less than EndValue, then the performance counter counts up. If StartValue
+ is greater than EndValue, then the performance counter counts down. For
+ example, a 64-bit free running counter that counts up would have a StartValue
+ of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+ that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+ @param StartValue The value the performance counter starts with when it
+ rolls over.
+ @param EndValue The value that the performance counter ends with before
+ it rolls over.
+
+ @return The frequency in Hz.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounterProperties (
+ OUT UINT64 *StartValue, OPTIONAL
+ OUT UINT64 *EndValue OPTIONAL
+ )
+{
+ if (StartValue != NULL) {
+ // Timer starts with the reload value
+ *StartValue = (UINT64)0ULL;
+ }
+
+ if (EndValue != NULL) {
+ // Timer counts up to 0xFFFFFFFF
+ *EndValue = 0xFFFFFFFF;
+ }
+
+ return 1000000;
+}
+
+/**
+ Converts elapsed ticks of performance counter to time in nanoseconds.
+
+ This function converts the elapsed ticks of running performance counter to
+ time value in unit of nanoseconds.
+
+ @param Ticks The number of elapsed ticks of running performance counter.
+
+ @return The elapsed time in nanoseconds.
+
+**/
+UINT64
+EFIAPI
+GetTimeInNanoSecond (
+ IN UINT64 Ticks
+)
+{
+ ASSERT (TRUE);
+ return 0;
+}
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/TimerLib/TimerLib.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/TimerLib/TimerLib.inf
new file mode 100644
index 000000000..b8b745aa3
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/TimerLib/TimerLib.inf
@@ -0,0 +1,41 @@
+#/** @file
+# Timer library implementation
+#
+#
+# Copyright (c) 2012, Samsung Electronics Co. All rights reserved.<BR>
+# 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 = Exynos4210TimerLib
+ FILE_GUID = 34cfa85e-a798-4e46-8d38-1843d7a0caea
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TimerLib
+
+ CONSTRUCTOR = TimerConstructor
+
+[Sources.common]
+ TimerLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ BaseLib
+
+[Pcd.common]
+ gExynosPkgTokenSpaceGuid.PcdPWMTimerBase
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeiLib.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeiLib.c
new file mode 100644
index 000000000..affc7da58
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeiLib.c
@@ -0,0 +1,182 @@
+/** @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 <PiPei.h>
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+VOID
+BuildMemoryTypeInformationHob (
+ VOID
+ );
+
+VOID
+InitMmu (
+ VOID
+ )
+{
+ ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable;
+ VOID *TranslationTableBase;
+ UINTN TranslationTableSize;
+
+ // Get Virtual Memory Map from the Platform Library
+ ArmPlatformGetVirtualMemoryMap(&MemoryTable);
+
+ //Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in
+ // DRAM (even at the top of DRAM as it is the first permanent memory allocation)
+ ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize);
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+ FileHandle - Handle of the file being invoked.
+ PeiServices - Describes the list of possible PEI Services.
+
+Returns:
+
+ Status - EFI_SUCCESS if the boot mode could be set
+
+--*/
+EFI_STATUS
+EFIAPI
+MemoryPeim (
+ IN EFI_PHYSICAL_ADDRESS UefiMemoryBase,
+ IN UINT64 UefiMemorySize
+ )
+{
+ EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
+ UINT64 ResourceLength;
+ EFI_PEI_HOB_POINTERS NextHob;
+ EFI_PHYSICAL_ADDRESS FdTop;
+ EFI_PHYSICAL_ADDRESS SystemMemoryTop;
+ EFI_PHYSICAL_ADDRESS ResourceTop;
+ BOOLEAN Found;
+
+ // Ensure PcdSystemMemorySize has been set
+ ASSERT (PcdGet32 (PcdSystemMemorySize) != 0);
+
+ //
+ // Now, the permanent memory has been installed, we can call AllocatePages()
+ //
+ ResourceAttributes = (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED
+ );
+
+ // Reserved the memory space occupied by the firmware volume
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_MAPPED_IO,
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE,
+ 0x10000000,//PcdGet32 (PcdPmuBase),
+ 0x087FFFFF
+ );
+
+ // Reserved the memory space occupied by the firmware volume
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ ResourceAttributes,
+ PcdGet32 (PcdSystemMemoryBase),
+ PcdGet32 (PcdSystemMemorySize)
+ );
+
+ SystemMemoryTop = PcdGet32 (PcdSystemMemoryBase) + PcdGet32 (PcdSystemMemorySize);
+ FdTop = PcdGet32(PcdFdBaseAddress) + PcdGet32(PcdFdSize);
+
+ // EDK2 does not have the concept of boot firmware copied into DRAM. To avoid the DXE
+ // core to overwrite this area we must mark the region with the attribute non-present
+ if ((PcdGet32 (PcdFdBaseAddress) >= PcdGet32 (PcdSystemMemoryBase)) && (FdTop <= SystemMemoryTop)) {
+ Found = FALSE;
+
+ // Search for System Memory Hob that contains the firmware
+ NextHob.Raw = GetHobList ();
+ while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) {
+ if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
+ (PcdGet32(PcdFdBaseAddress) >= NextHob.ResourceDescriptor->PhysicalStart) &&
+ (FdTop <= NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength))
+ {
+ ResourceAttributes = NextHob.ResourceDescriptor->ResourceAttribute;
+ ResourceLength = NextHob.ResourceDescriptor->ResourceLength;
+ ResourceTop = NextHob.ResourceDescriptor->PhysicalStart + ResourceLength;
+
+ if (PcdGet32(PcdFdBaseAddress) == NextHob.ResourceDescriptor->PhysicalStart) {
+ if (SystemMemoryTop == FdTop) {
+ NextHob.ResourceDescriptor->ResourceAttribute = ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT;
+ } else {
+ // Create the System Memory HOB for the firmware with the non-present attribute
+ BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
+ ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT,
+ PcdGet32(PcdFdBaseAddress),
+ PcdGet32(PcdFdSize));
+
+ DEBUG((EFI_D_ERROR, "PcdFdBaseAddress : 0x%X, PcdFdSize: 0x%X\n", PcdGet32(PcdFdBaseAddress),PcdGet32(PcdFdSize)));
+
+ // Top of the FD is system memory available for UEFI
+ NextHob.ResourceDescriptor->PhysicalStart += PcdGet32(PcdFdSize);
+ NextHob.ResourceDescriptor->ResourceLength -= PcdGet32(PcdFdSize);
+ }
+ } else {
+ // Create the System Memory HOB for the firmware with the non-present attribute
+ BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
+ ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT,
+ PcdGet32(PcdFdBaseAddress),
+ PcdGet32(PcdFdSize));
+ DEBUG((EFI_D_ERROR, "PcdFdBaseAddress : 0x%X, PcdFdSize: 0x%X\n", PcdGet32(PcdFdBaseAddress),PcdGet32(PcdFdSize)));
+
+ // Update the HOB
+ NextHob.ResourceDescriptor->ResourceLength = PcdGet32(PcdFdBaseAddress) - NextHob.ResourceDescriptor->PhysicalStart;
+
+ // If there is some memory available on the top of the FD then create a HOB
+ if (FdTop < NextHob.ResourceDescriptor->PhysicalStart + ResourceLength) {
+ // Create the System Memory HOB for the remaining region (top of the FD)
+ BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
+ ResourceAttributes,
+ FdTop,
+ ResourceTop - FdTop);
+ DEBUG((EFI_D_ERROR, "FdTop : 0x%X, ResourceTop - FdTop : 0x%X\n", FdTop, ResourceTop - FdTop));
+ }
+ }
+ Found = TRUE;
+ break;
+ }
+ NextHob.Raw = GET_NEXT_HOB (NextHob);
+ }
+
+ ASSERT(Found);
+ }
+
+ // Build Memory Allocation Hob
+ InitMmu ();
+
+ if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
+ // Optional feature that helps prevent EFI memory map fragmentation.
+ BuildMemoryTypeInformationHob ();
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeiLib.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeiLib.inf
new file mode 100644
index 000000000..3afbfc8d4
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeiLib.inf
@@ -0,0 +1,69 @@
+#/** @file
+#
+# Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+# 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 = ArmMemoryInitPeiLib
+ FILE_GUID = 55ddb6e0-70b5-11e0-b33e-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformPeiLib
+
+[Sources]
+ MemoryInitPeiLib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ HobLib
+ ArmLib
+ ArmPlatformLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+
+[Ppis]
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
+
+ gExynosPkgTokenSpaceGuid.PcdPmuBase
+
+[depex]
+ TRUE
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.c
new file mode 100644
index 000000000..0fc6b4aa9
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.c
@@ -0,0 +1,157 @@
+/** @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 <PiPei.h>
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/BootInRecoveryMode.h>
+#include <Guid/MemoryTypeInformation.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/ArmPlatformLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+
+EFI_STATUS
+EFIAPI
+MemoryPeim (
+ IN EFI_PHYSICAL_ADDRESS UefiMemoryBase,
+ IN UINT64 UefiMemorySize
+ );
+
+// May want to put this into a library so you only need the PCD settings if you are using the feature?
+VOID
+BuildMemoryTypeInformationHob (
+ VOID
+ )
+{
+ EFI_MEMORY_TYPE_INFORMATION Info[10];
+
+ Info[0].Type = EfiACPIReclaimMemory;
+ Info[0].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory);
+ Info[1].Type = EfiACPIMemoryNVS;
+ Info[1].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS);
+ Info[2].Type = EfiReservedMemoryType;
+ Info[2].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiReservedMemoryType);
+ Info[3].Type = EfiRuntimeServicesData;
+ Info[3].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesData);
+ Info[4].Type = EfiRuntimeServicesCode;
+ Info[4].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode);
+ Info[5].Type = EfiBootServicesCode;
+ Info[5].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesCode);
+ Info[6].Type = EfiBootServicesData;
+ Info[6].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesData);
+ Info[7].Type = EfiLoaderCode;
+ Info[7].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderCode);
+ Info[8].Type = EfiLoaderData;
+ Info[8].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderData);
+
+ DEBUG ((EFI_D_ERROR, "BuildMemoryTypeInformationHob PcdMemoryTypeEfiRuntimeServicesCode: %d, PcdMemoryTypeEfiRuntimeServicesData: %d\n", Info[4].NumberOfPages, Info[3].NumberOfPages));
+ // Terminator for the list
+ Info[9].Type = EfiMaxMemoryType;
+ Info[9].NumberOfPages = 0;
+
+ BuildGuidDataHob (&gEfiMemoryTypeInformationGuid, &Info, sizeof (Info));
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+ FileHandle - Handle of the file being invoked.
+ PeiServices - Describes the list of possible PEI Services.
+
+Returns:
+
+ Status - EFI_SUCCESS if the boot mode could be set
+
+--*/
+EFI_STATUS
+EFIAPI
+InitializeMemory (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN SystemMemoryBase;
+ UINTN SystemMemoryTop;
+ UINTN FdBase;
+ UINTN FdTop;
+ UINTN UefiMemoryBase;
+
+ DEBUG ((EFI_D_ERROR, "Memory Init PEIM Loaded\n"));
+
+ // Ensure PcdSystemMemorySize has been set
+ ASSERT (FixedPcdGet32 (PcdSystemMemorySize) != 0);
+
+ SystemMemoryBase = (UINTN)FixedPcdGet32 (PcdSystemMemoryBase);
+ SystemMemoryTop = SystemMemoryBase + (UINTN)FixedPcdGet32 (PcdSystemMemorySize);
+ FdBase = (UINTN)PcdGet32 (PcdFdBaseAddress);
+ FdTop = FdBase + (UINTN)PcdGet32 (PcdFdSize);
+
+ DEBUG ((EFI_D_ERROR, "SystemMemoryBase : 0x%X, SystemMemoryTop : 0x%X, FdBase : 0x%X, FdTop : 0x%X\n", SystemMemoryBase, SystemMemoryTop, FdBase, FdTop));
+ //
+ // Initialize the System Memory (DRAM)
+ //
+ if (!FeaturePcdGet (PcdSystemMemoryInitializeInSec)) {
+ // In case the DRAM has not been initialized by the secure firmware
+ ArmPlatformInitializeSystemMemory ();
+ }
+
+ //
+ // Declare the UEFI memory to PEI
+ //
+
+ // In case the firmware has been shadowed in the System Memory
+ if ((FdBase >= SystemMemoryBase) && (FdTop <= SystemMemoryTop)) {
+ // Check if there is enough space between the top of the system memory and the top of the
+ // firmware to place the UEFI memory (for PEI & DXE phases)
+ if (SystemMemoryTop - FdTop >= FixedPcdGet32 (PcdSystemMemoryUefiRegionSize)) {
+ UefiMemoryBase = SystemMemoryTop - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+ } else {
+ // Check there is enough space for the UEFI memory
+ ASSERT (SystemMemoryBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize) <= FdBase);
+
+ UefiMemoryBase = FdBase - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+ }
+ } else {
+ // Check the Firmware does not overlapped with the system memory
+ ASSERT ((FdBase < SystemMemoryBase) || (FdBase >= SystemMemoryTop));
+ ASSERT ((FdTop <= SystemMemoryBase) || (FdTop > SystemMemoryTop));
+
+ UefiMemoryBase = SystemMemoryTop - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+ }
+
+ DEBUG ((EFI_D_ERROR, "UefiMemoryBase : 0x%X, PcdSystemMemoryUefiRegionSize : 0x%X\n", UefiMemoryBase, FixedPcdGet32(PcdSystemMemoryUefiRegionSize)));
+ Status = PeiServicesInstallPeiMemory (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
+ ASSERT_EFI_ERROR (Status);
+
+ // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
+ Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.inf
new file mode 100644
index 000000000..23d245ef1
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.inf
@@ -0,0 +1,75 @@
+#/** @file
+#
+# Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+# 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 = MemoryInit
+ FILE_GUID = c61ef796-b50d-4f98-9f78-4f6f79d800d5
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeMemory
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC ARM
+#
+
+[Sources]
+ MemoryInitPeim.c
+ MemoryInitPeiLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ DebugLib
+ HobLib
+ ArmLib
+ ArmPlatformLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+
+[FeaturePcd]
+ gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gArmTokenSpaceGuid.PcdSystemMemorySize
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
+
+ gExynosPkgTokenSpaceGuid.PcdPmuBase
+[Depex]
+ TRUE
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeiLib.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeiLib.c
new file mode 100644
index 000000000..813c1d349
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeiLib.c
@@ -0,0 +1,30 @@
+/** @file
+*
+* Copyright (c) 2011-2012, 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 <PiPei.h>
+
+#include <Library/ArmPlatformLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+ VOID
+ )
+{
+ BuildFvHob (PcdGet32(PcdFvBaseAddress), PcdGet32(PcdFvSize));
+
+ return EFI_SUCCESS;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeiLib.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeiLib.inf
new file mode 100644
index 000000000..01f935952
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeiLib.inf
@@ -0,0 +1,53 @@
+#/** @file
+#
+# Copyright (c) 2011-2012, 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 = ArmPlatformPeiLib
+ FILE_GUID = 49d37060-70b5-11e0-aa2d-0002a5d5c51b
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformPeiLib
+
+[Sources]
+ PlatformPeiLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ HobLib
+ ArmPlatformLib
+
+[Ppis]
+ gEfiPeiMasterBootModePpiGuid # PPI ALWAYS_PRODUCED
+ gEfiPeiBootInRecoveryModePpiGuid # PPI SOMETIMES_PRODUCED
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdFvSize
+
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
+
+[depex]
+ TRUE
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.c
new file mode 100644
index 000000000..8663409ed
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.c
@@ -0,0 +1,138 @@
+/** @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 <PiPei.h>
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Ppi/ArmGlobalVariable.h>
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/BootInRecoveryMode.h>
+#include <Ppi/GuidedSectionExtraction.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/ArmPlatformLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+
+#include <Guid/ArmGlobalVariableHob.h>
+
+EFI_STATUS
+EFIAPI
+InitializePlatformPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ );
+
+EFI_STATUS
+EFIAPI
+PlatformPeim (
+ VOID
+ );
+
+//
+// Module globals
+//
+EFI_PEI_PPI_DESCRIPTOR mPpiListBootMode = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMasterBootModePpiGuid,
+ NULL
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiBootInRecoveryModePpiGuid,
+ NULL
+};
+
+VOID
+EFIAPI
+BuildGlobalVariableHob (
+ IN EFI_PHYSICAL_ADDRESS GlobalVariableBase,
+ IN UINT32 GlobalVariableSize
+ )
+{
+ EFI_STATUS Status;
+ ARM_HOB_GLOBAL_VARIABLE *Hob;
+
+ Status = PeiServicesCreateHob (EFI_HOB_TYPE_GUID_EXTENSION, sizeof (ARM_HOB_GLOBAL_VARIABLE), (VOID**)&Hob);
+ if (!EFI_ERROR(Status)) {
+ CopyGuid (&(Hob->Header.Name), &gArmGlobalVariableGuid);
+ Hob->GlobalVariableBase = GlobalVariableBase;
+ Hob->GlobalVariableSize = GlobalVariableSize;
+ }
+}
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+ FileHandle - Handle of the file being invoked.
+ PeiServices - Describes the list of possible PEI Services.
+
+Returns:
+
+ Status - EFI_SUCCESS if the boot mode could be set
+
+--*/
+EFI_STATUS
+EFIAPI
+InitializePlatformPeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN BootMode;
+ ARM_GLOBAL_VARIABLE_PPI *ArmGlobalVariablePpi;
+ EFI_PHYSICAL_ADDRESS GlobalVariableBase;
+
+ DEBUG ((EFI_D_ERROR, "Platform PEIM Loaded\n"));
+
+ PlatformPeim ();
+
+ Status = PeiServicesLocatePpi (&gArmGlobalVariablePpiGuid, 0, NULL, (VOID**)&ArmGlobalVariablePpi);
+ if (!EFI_ERROR(Status)) {
+ Status = ArmGlobalVariablePpi->GetGlobalVariableMemory (&GlobalVariableBase);
+
+ if (!EFI_ERROR(Status)) {
+ // Declare the Global Variable HOB
+ BuildGlobalVariableHob (GlobalVariableBase, FixedPcdGet32 (PcdPeiGlobalVariableSize));
+ }
+ }
+
+ BootMode = ArmPlatformGetBootMode ();
+ Status = (**PeiServices).SetBootMode (PeiServices, (UINT8) BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = (**PeiServices).InstallPpi (PeiServices, &mPpiListBootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ if (BootMode == BOOT_IN_RECOVERY_MODE) {
+ Status = (**PeiServices).InstallPpi (PeiServices, &mPpiListRecoveryBootMode);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.inf
new file mode 100755
index 000000000..cd1cd7a51
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.inf
@@ -0,0 +1,69 @@
+#/** @file
+#
+# Copyright (c) 2011-2012, 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 = PlatformPei
+ FILE_GUID = 2ad0fc59-2314-4bf3-8633-13fa22a624a0
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializePlatformPeim
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC ARM
+#
+
+[Sources]
+ PlatformPeim.c
+ PlatformPeiLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ DebugLib
+ HobLib
+ ArmPlatformLib
+
+[Ppis]
+ gEfiPeiMasterBootModePpiGuid # PPI ALWAYS_PRODUCED
+ gEfiPeiBootInRecoveryModePpiGuid # PPI SOMETIMES_PRODUCED
+ gArmGlobalVariablePpiGuid
+
+[Guids]
+ gArmGlobalVariableGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+ gArmTokenSpaceGuid.PcdFdSize
+
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdFvSize
+
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
+
+ gArmPlatformTokenSpaceGuid.PcdPeiGlobalVariableSize
+
+[Depex]
+ TRUE
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Helper.S b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Helper.S
new file mode 100644
index 000000000..ad53ab320
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Helper.S
@@ -0,0 +1,84 @@
+#========================================================================================
+# Copyright (c) 2011-2012, 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.
+#
+#=======================================================================================
+
+#start of the code section
+.text
+.align 3
+
+GCC_ASM_EXPORT(return_from_exception)
+GCC_ASM_EXPORT(enter_monitor_mode)
+GCC_ASM_EXPORT(copy_cpsr_into_spsr)
+GCC_ASM_EXPORT(set_non_secure_mode)
+
+# r0: Monitor World EntryPoint
+# r1: MpId
+# r2: Secure Monitor mode stack
+ASM_PFX(enter_monitor_mode):
+ cmp r2, #0 @ If a Secure Monitor stack base has not been defined then use the Secure stack
+ moveq r2, sp
+
+ mrs r4, cpsr @ Save current mode (SVC) in r4
+ bic r3, r4, #0x1f @ Clear all mode bits
+ orr r3, r3, #0x16 @ Set bits for Monitor mode
+ msr cpsr_cxsf, r3 @ We are now in Monitor Mode
+
+ mov sp, r2 @ Set the stack of the Monitor Mode
+
+ mov lr, r0 @ Use the pass entrypoint as lr
+
+ msr spsr_cxsf, r4 @ Use saved mode for the MOVS jump to the kernel
+
+ mov r4, r0 @ Swap EntryPoint and MpId registers
+ mov r0, r1
+
+ bx r4
+
+# We cannot use the instruction 'movs pc, lr' because the caller can be written either in ARM or Thumb2 assembler.
+# When we will jump into this function, we will set the CPSR flag to ARM assembler. By copying directly 'lr' into
+# 'pc'; we will not change the CPSR flag and it will crash.
+# The way to fix this limitation is to do the movs into the ARM assmbler code and then do a 'bx'.
+ASM_PFX(return_from_exception):
+ ldr lr, returned_exception
+
+ #The following instruction breaks the code.
+ #movs pc, lr
+ mrs r2, cpsr
+ bic r2, r2, #0x1f
+ orr r2, r2, #0x13
+ msr cpsr_c, r2
+
+returned_exception: @ We are now in non-secure state
+ bx r0
+
+# Save the current Program Status Register (PSR) into the Saved PSR
+ASM_PFX(copy_cpsr_into_spsr):
+ mrs r0, cpsr
+ msr spsr_cxsf, r0
+ bx lr
+
+# Set the Non Secure Mode
+ASM_PFX(set_non_secure_mode):
+ push { r1 }
+ and r0, r0, #0x1f @ Keep only the mode bits
+ mrs r1, spsr @ Read the spsr
+ bic r1, r1, #0x1f @ Clear all mode bits
+ orr r1, r1, r0
+ msr spsr_cxsf, r1 @ write back spsr (may have caused a mode switch)
+ isb
+ pop { r1 }
+ bx lr @ return (hopefully thumb-safe!)
+
+dead:
+ b dead
+
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Helper.asm b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Helper.asm
new file mode 100644
index 000000000..c4eaec1a7
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Helper.asm
@@ -0,0 +1,75 @@
+//
+// Copyright (c) 2011-2012, 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.
+//
+//
+
+ EXPORT return_from_exception
+ EXPORT enter_monitor_mode
+ EXPORT copy_cpsr_into_spsr
+ EXPORT set_non_secure_mode
+
+ AREA Helper, CODE, READONLY
+
+// r0: Monitor World EntryPoint
+// r1: MpId
+// r2: Secure Monitor mode stack
+enter_monitor_mode
+ cmp r2, #0 // If a Secure Monitor stack base has not been defined then use the Secure stack
+ moveq r2, sp
+
+ mrs r4, cpsr // Save current mode (SVC) in r4
+ bic r3, r4, #0x1f // Clear all mode bits
+ orr r3, r3, #0x16 // Set bits for Monitor mode
+ msr cpsr_cxsf, r3 // We are now in Monitor Mode
+
+ mov sp, r2 // Set the stack of the Monitor Mode
+
+ mov lr, r0 // Use the pass entrypoint as lr
+
+ msr spsr_cxsf, r4 // Use saved mode for the MOVS jump to the kernel
+
+ mov r4, r0 // Swap EntryPoint and MpId registers
+ mov r0, r1
+
+ bx r4
+
+// We cannot use the instruction 'movs pc, lr' because the caller can be written either in ARM or Thumb2 assembler.
+// When we will jump into this function, we will set the CPSR flag to ARM assembler. By copying directly 'lr' into
+// 'pc'; we will not change the CPSR flag and it will crash.
+// The way to fix this limitation is to do the movs into the ARM assmbler code and then do a 'bx'.
+return_from_exception
+ adr lr, returned_exception
+ movs pc, lr
+returned_exception // We are now in non-secure state
+ bx r0
+
+// Save the current Program Status Register (PSR) into the Saved PSR
+copy_cpsr_into_spsr
+ mrs r0, cpsr
+ msr spsr_cxsf, r0
+ bx lr
+
+// Set the Non Secure Mode
+set_non_secure_mode
+ push { r1 }
+ and r0, r0, #0x1f // Keep only the mode bits
+ mrs r1, spsr // Read the spsr
+ bic r1, r1, #0x1f // Clear all mode bits
+ orr r1, r1, r0
+ msr spsr_cxsf, r1 // write back spsr (may have caused a mode switch)
+ isb
+ pop { r1 }
+ bx lr // return (hopefully thumb-safe!)
+
+dead
+ B dead
+
+ END
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.c
new file mode 100644
index 000000000..3c4f4983f
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.c
@@ -0,0 +1,222 @@
+/** @file
+* Main file supporting the SEC Phase on ARM Platforms
+*
+* Copyright (c) 2011-2012, 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/ArmTrustedMonitorLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/ArmGicLib.h>
+#include <Library/ArmCpuLib.h>
+#include <Library/IoLib.h>
+#include <Library/ArmPlatformLib.h>
+#include "SecInternal.h"
+#include "Smc.h"
+
+#define SerialPrint(txt) SerialPortWrite ((UINT8*)txt, AsciiStrLen(txt)+1);
+
+extern VOID *monitor_vector_table;
+
+#define ISRAM_ADDRESS 0x02020000
+#define EXTERNAL_FUNC_ADDRESS (ISRAM_ADDRESS + 0x0030)
+#define MSH_ReadFromFIFO_eMMC_ADDRESS (EXTERNAL_FUNC_ADDRESS + 0x14)
+#define MSH_EndBootOp_eMMC_ADDRESS (EXTERNAL_FUNC_ADDRESS + 0x18)
+
+#define SDMMC_ReadBlocks(uStartBlk, uNumOfBlks, uDstAddr) \
+ (((VOID(*)(UINT32, UINT32, UINT32*))(*((UINT32 *)EXTERNAL_FUNC_ADDRESS)))(uStartBlk, uNumOfBlks, uDstAddr))
+
+#define EMMC_ReadBlocks(uNumOfBlks, uDstAddr) \
+ (((VOID(*)(UINT32, UINT32*))(*((UINT32 *)MSH_ReadFromFIFO_eMMC_ADDRESS)))(uNumOfBlks, uDstAddr))
+
+#define EMMC_EndBootOp() \
+ (((VOID(*)())(*((UINT32 *)MSH_EndBootOp_eMMC_ADDRESS)))())
+
+VOID CopyFirmwareFromSDMMC(VOID)
+{
+ SDMMC_ReadBlocks(49, ((1536*1024)/512), (UINT32 *)0x40000000);
+}
+
+VOID CopyFirmwareFromEMMC(VOID)
+{
+ if (FixedPcdGetBool (PcdTrustzoneSupport)) {
+ load_uefi_image(EMMC);
+ } else {
+ EMMC_ReadBlocks(((1536*1024)/512), (UINT32 *)0x40000000);
+ EMMC_EndBootOp();
+ }
+}
+
+VOID ColdBootForTzsw(UINT32 StartupAddr)
+{
+ coldboot(EMMC, StartupAddr);
+}
+
+VOID
+CEntryPoint (
+ IN UINTN MpId
+ )
+{
+ CHAR8 Buffer[100];
+ UINTN CharCount;
+ UINTN JumpAddress;
+
+ if (!FixedPcdGetBool (PcdTrustzoneSupport)) {
+ // Invalidate the data cache. Doesn't have to do the Data cache clean.
+ ArmInvalidateDataCache();
+
+ // Invalidate Instruction Cache
+ ArmInvalidateInstructionCache();
+
+ // Invalidate I & D TLBs
+ ArmInvalidateInstructionAndDataTlb();
+
+ // CPU specific settings
+ ArmCpuSetup (MpId);
+
+ // Enable Floating Point Coprocessor if supported by the platform
+ if (FixedPcdGet32 (PcdVFPEnabled)) {
+ ArmEnableVFP();
+ }
+ // Initialize peripherals that must be done at the early stage
+ // Example: Some L2 controller, interconnect, clock, DMC, etc
+ ArmPlatformSecInitialize (MpId);
+ }
+
+ // Primary CPU clears out the SCU tag RAMs, secondaries wait
+ if (ArmPlatformIsPrimaryCore (MpId)) {
+ if (ArmIsMpCore()) {
+ // Is UEFI built as it is assumed that TZSW is running?
+ // PcdTrustzoneSupport==1: YES.
+ // PcdTrustzoneSupport==1: NO. UEFI is built as it is assumed that TZSW is not needed.
+ if (FixedPcdGetBool (PcdTrustzoneSupport)) {
+ // IS UEFI executed after TZSW ran? (In other words, UEFI is fuzed and running?
+ // ArmReadNsacr()==1: YES.
+ // ArmReadNsacr()!=1: No. UEFI(assumed TZSW is running) is executed after uploaded with T32(not fuzed)
+ if(ArmReadNsacr()) {
+ exynos_smc(SMC_CMD_CPU1BOOT, 0, 0, 0);
+ }
+ }
+ }
+
+ // SEC phase needs to run library constructors by hand. This assumes we are linked against the SerialLib
+ // In non SEC modules the init call is in autogenerated code.
+ SerialPortInitialize ();
+
+ // Start talking
+ if (FixedPcdGetBool (PcdTrustzoneSupport)) {
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Secure firmware (version %s built at %a on %a)\n\r",
+ (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
+ } else {
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Boot firmware (version %s built at %a on %a)\n\r",
+ (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
+ }
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
+
+ // Initialize the Debug Agent for Source Level Debugging
+ InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, NULL, NULL);
+ SaveAndSetDebugTimerInterrupt (TRUE);
+
+ // Enable the GIC distributor and CPU Interface
+ // - no other Interrupts are enabled, doesn't have to worry about the priority.
+ // - all the cores are in secure state, use secure SGI's
+ ArmGicEnableDistributor (PcdGet32(PcdGicDistributorBase));
+ ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
+
+ } else {
+ // Enable the GIC CPU Interface
+ ArmGicEnableInterruptInterface (PcdGet32(PcdGicInterruptInterfaceBase));
+ }
+
+ // Enable Full Access to CoProcessors
+ ArmWriteCpacr (CPACR_CP_FULL_ACCESS);
+
+ // With Trustzone support the transition from Sec to Normal world is done by return_from_exception().
+ // If we want to keep this function call we need to ensure the SVC's SPSR point to the same Program
+ // Status Register as the the current one (CPSR).
+ copy_cpsr_into_spsr ();
+
+ // Call the Platform specific function to execute additional actions if required
+ JumpAddress = PcdGet32 (PcdFvBaseAddress);
+ ArmPlatformSecExtraAction (MpId, &JumpAddress);
+
+ NonTrustedWorldTransition (MpId, JumpAddress);
+
+ ASSERT (0); // We must never return from the above function
+}
+
+VOID
+TrustedWorldInitialization (
+ IN UINTN MpId
+ )
+{
+ UINTN JumpAddress;
+
+ //-------------------- Monitor Mode ---------------------
+
+ // Set up Monitor World (Vector Table, etc)
+ ArmSecureMonitorWorldInitialize ();
+
+ // Transfer the interrupt to Non-secure World
+ ArmGicSetupNonSecure (MpId, PcdGet32(PcdGicDistributorBase), PcdGet32(PcdGicInterruptInterfaceBase));
+
+ // Initialize platform specific security policy
+ ArmPlatformSecTrustzoneInit (MpId);
+
+ // Setup the Trustzone Chipsets
+ if (ArmPlatformIsPrimaryCore (MpId)) {
+ if (ArmIsMpCore()) {
+ // Signal the secondary core the Security settings is done (event: EVENT_SECURE_INIT)
+ ArmCallSEV ();
+ }
+ } else {
+ // The secondary cores need to wait until the Trustzone chipsets configuration is done
+ // before switching to Non Secure World
+
+ // Wait for the Primary Core to finish the initialization of the Secure World (event: EVENT_SECURE_INIT)
+ ArmCallWFE ();
+ }
+
+ // Call the Platform specific function to execute additional actions if required
+ JumpAddress = PcdGet32 (PcdFvBaseAddress);
+ ArmPlatformSecExtraAction (MpId, &JumpAddress);
+
+ // Write to CP15 Non-secure Access Control Register
+ ArmWriteNsacr (PcdGet32 (PcdArmNsacr));
+
+ // CP15 Secure Configuration Register
+ ArmWriteScr (PcdGet32 (PcdArmScr));
+
+ NonTrustedWorldTransition (MpId, JumpAddress);
+}
+
+VOID
+NonTrustedWorldTransition (
+ IN UINTN MpId,
+ IN UINTN JumpAddress
+ )
+{
+ // If PcdArmNonSecModeTransition is defined then set this specific mode to CPSR before the transition
+ // By not set, the mode for Non Secure World is SVC
+ if (PcdGet32 (PcdArmNonSecModeTransition) != 0) {
+ set_non_secure_mode ((ARM_PROCESSOR_MODE)PcdGet32 (PcdArmNonSecModeTransition));
+ }
+
+ return_from_exception (JumpAddress);
+ //-------------------- Non Secure Mode ---------------------
+
+ // PEI Core should always load and never return
+ ASSERT (FALSE);
+}
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.inf b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.inf
new file mode 100644
index 000000000..1cda8c3ad
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.inf
@@ -0,0 +1,85 @@
+#/** @file
+# SEC - Reset vector code that jumps to C and loads DXE core
+#
+# 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 = ArmPlatformSec
+ FILE_GUID = c536bbfe-c813-4e48-9f90-01fe1ecf9d54
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+[Sources.ARM]
+ Helper.asm | RVCT
+ Helper.S | GCC
+ Sec.c
+ SecEntryPoint.S | GCC
+ SecEntryPoint.asm | RVCT
+ Smc.c
+ SecFromTzsw.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec
+
+[LibraryClasses]
+ ArmCpuLib
+ ArmLib
+ ArmPlatformSecLib
+ ArmTrustedMonitorLib
+ BaseLib
+ DebugLib
+ DebugAgentLib
+ IoLib
+ ArmGicLib
+ PrintLib
+ SerialPortLib
+
+[FeaturePcd]
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
+
+[FixedPcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
+
+ gArmTokenSpaceGuid.PcdTrustzoneSupport
+ gArmTokenSpaceGuid.PcdVFPEnabled
+
+ gArmTokenSpaceGuid.PcdArmScr
+ gArmTokenSpaceGuid.PcdArmNsacr
+ gArmTokenSpaceGuid.PcdArmNonSecModeTransition
+
+ gArmTokenSpaceGuid.PcdSecureFvBaseAddress
+ gArmTokenSpaceGuid.PcdSecureFvSize
+
+ gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdFdBaseAddress
+
+ gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecPrimaryStackSize
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecSecondaryStackSize
+ gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase
+ gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize
+
+ gArmTokenSpaceGuid.PcdGicDistributorBase
+ gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
+
+ gArmPlatformTokenSpaceGuid.PcdSecGlobalVariableSize
+
+ gExynosPkgTokenSpaceGuid.PcdMpSharedArgsBase
+
+ gExynosPkgTokenSpaceGuid.PcdiRamStackBase
+ gExynosPkgTokenSpaceGuid.PcdiRamStackSize
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecEntryPoint.S b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecEntryPoint.S
new file mode 100644
index 000000000..aecbc939f
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecEntryPoint.S
@@ -0,0 +1,287 @@
+//
+// Copyright (c) 2011-2012, 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 <AutoGen.h>
+#include <AsmMacroIoLib.h>
+#include <Library/ArmPlatformLib.h>
+#include <ArmPlatform.h>
+#include "SecInternal.h"
+
+.text
+.align 3
+
+GCC_ASM_IMPORT(CEntryPoint)
+GCC_ASM_IMPORT(ArmPlatformIsPrimaryCore)
+GCC_ASM_IMPORT(CopyFirmwareFromEMMC)
+GCC_ASM_IMPORT(CopyFirmwareFromSDMMC)
+GCC_ASM_IMPORT(ArmPlatformClockInitialize)
+GCC_ASM_IMPORT(ArmPlatformSecBootAction)
+GCC_ASM_IMPORT(ArmPlatformSecBootMemoryInit)
+GCC_ASM_IMPORT(ArmDisableInterrupts)
+GCC_ASM_IMPORT(ArmDisableCachesAndMmu)
+GCC_ASM_IMPORT(ArmEnableBranchPrediction)
+GCC_ASM_IMPORT(ArmReadMpidr)
+GCC_ASM_IMPORT(ArmCallWFE)
+GCC_ASM_IMPORT(_SecEntryFromTzsw)
+GCC_ASM_EXPORT(_ModuleEntryPoint)
+
+SecStartupAddr: .word ASM_PFX(_SecEntryFromTzsw)
+StartupAddr: .word ASM_PFX(CEntryPoint)
+
+// Convert the (ClusterId,CoreId) into a Core Position
+// 0x0F03 is the magic value for ARM_CORE_MASK | ARM_CLUSTER_MASK
+//Core is 0-1 bits and cluster is 8-11 bits
+#define GetCorePositionFromMpId(Pos, MpId, Tmp) \
+ ldr Tmp, =0x0F03 ; \
+ and MpId, Tmp ; \
+ lsr Pos, MpId, #6 ; \
+ and Tmp, MpId, #3 ; \
+ add Pos, Pos, Tmp
+
+// Reserve a region at the top of the IRAM Core stack
+// for Global variables for the XIP phase
+#define SetiRamStack(StackTop, GlobalSize, Tmp) \
+ and Tmp, GlobalSize, #7 ; \
+ rsbne Tmp, Tmp, #8 ; \
+ add GlobalSize, GlobalSize, Tmp ; \
+ sub sp, StackTop, GlobalSize ; \
+ ; \
+ mov Tmp, sp ; \
+ mov GlobalSize, #0x0 ; \
+_SetiRamStackInitGlobals: ; \
+ cmp Tmp, StackTop ; \
+ beq _SetiRamStackEnd ; \
+ str GlobalSize, [Tmp], #4 ; \
+ b _SetiRamStackInitGlobals ; \
+_SetiRamStackEnd:
+
+
+ASM_PFX(_ModuleEntryPoint):
+ // First ensure all interrupts are disabled
+ bl ASM_PFX(ArmDisableInterrupts)
+
+ // Ensure that the MMU and caches are off
+ bl ASM_PFX(ArmDisableCachesAndMmu)
+
+ // Jump to Platform Specific Boot Action function
+ blx ASM_PFX(ArmPlatformSecBootAction)
+
+ # Enable branch prediction
+ bl ASM_PFX(ArmEnableBranchPrediction)
+
+ # TZPC1_DECPROT1Set (work-around for connecting T32 in SD booting mode)
+// ldr r0, =0x10110810
+// mov r1, #0xF
+// str r1, [r0]
+// dsb
+// isb
+// sev
+
+// ldr r0, =0x1
+// ldr r1, =0x2
+//infloop:
+// cmp r0, r1
+// bme infloop
+
+
+_IdentifyCpu:
+ // Identify CPU ID
+ bl ASM_PFX(ArmReadMpidr)
+ // Keep a copy of the MpId register value
+ mov r5, r0
+
+ // Is it the Primary Core ?
+ bl ASM_PFX(ArmPlatformIsPrimaryCore)
+ cmp r0, #1
+
+ // Only the primary core initialize the memory (SMC)
+ beq _InitMem
+
+_WaitInitMem:
+ // Wait for the primary core to initialize the initial memory (event: BOOT_MEM_INIT)
+ bl ASM_PFX(ArmCallWFE)
+ // Now the Init Mem is initialized, we setup the secondary core stacks
+ b _SetupSecondaryCoreStack
+
+_InitMem:
+ // Initialize Init Boot Memory
+ mov r0, pc
+ ldr r1, =0x40000000
+ cmp r0, r1
+ bgt _SetupPrimaryCoreStack
+
+ bl ASM_PFX(ArmPlatformClockInitialize)
+
+ LoadConstantToReg (FixedPcdGet32(PcdiRamStackBase), r1)
+ LoadConstantToReg (FixedPcdGet32(PcdiRamStackSize), r2)
+
+ // The reserved space for global variable must be 8-bytes aligned for pushing
+ // 64-bit variable on the stack
+ SetiRamStack (r1, r2, r3)
+
+ bl ASM_PFX(ArmPlatformSecBootMemoryInit)
+
+_SetupPrimaryCoreStack:
+ // Get the top of the primary stacks (and the base of the secondary stacks)
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r1)
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecPrimaryStackSize), r2)
+ add r1, r1, r2
+
+ LoadConstantToReg (FixedPcdGet32(PcdSecGlobalVariableSize), r2)
+
+ // The reserved space for global variable must be 8-bytes aligned for pushing
+ // 64-bit variable on the stack
+ SetPrimaryStack (r1, r2, r3)
+
+ mov r0, pc
+ ldr r1, =0x40000000
+ cmp r0, r1
+ bgt _PrepareArguments_NonTZ
+
+ b _CopyFirmware
+
+_SetupSecondaryCoreStack:
+ // Get the top of the primary stacks (and the base of the secondary stacks)
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r1)
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecPrimaryStackSize), r2)
+ add r1, r1, r2
+
+ // Get the Core Position (ClusterId * 4) + CoreId
+ GetCorePositionFromMpId(r0, r5, r2)
+ // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack
+ add r0, r0, #1
+
+ // StackOffset = CorePos * StackSize
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecSecondaryStackSize), r2)
+ mul r0, r0, r2
+ // SP = StackBase + StackOffset
+ add sp, r1, r0
+
+ b _PrepareArguments_NonTZ
+
+_PrepareArguments:
+ // Move sec startup address into a data register
+ // Ensure we're jumping to FV version of the code (not boot remapped alias)
+ LoadConstantToReg (FixedPcdGet32(PcdTrustzoneSupport), r2)
+ cmp r2, #0x1 /* TrustZone Enable */
+ beq _PrepareArguments_TZ
+
+_PrepareArguments_NonTZ:
+ ldr r3, StartupAddr
+ // Jump to SEC C code
+ // r0 = mp_id
+ mov r0, r5
+ blx r3
+
+_PrepareArguments_TZ:
+ /* Load IRAM_NS on IRAM_NS_BASE */
+ /* TZSW will call IRAM_NS code */
+ bl relocate_code
+
+ /* Jump to Coldboot in TZSW */
+ ldr r0, SecStartupAddr
+ b _ColdBootTzsw
+
+_CopyFirmware:
+ ldr r0, =Exynos5250_CMU_BASE
+ ldr r2, =CLK_DIV_FSYS2_OFFSET
+ ldr r1, [r0, r2]
+ bic r1, r1, #(0xFF << 8)
+ bic r1, r1, #(0xF)
+ orr r1, r1, #(0x9<< 8)
+ orr r1, r1, #0x3
+ str r1, [r0, r2]
+
+ /* Read booting information */
+ ldr r0, =0x10040000
+ ldr r1, [r0,#0x0]
+ bic r2, r1, #0xffffffc1
+
+ cmp r2, #0x8
+ beq _CopyFirmwareEMMC
+
+ /* SD/MMC BOOT */
+ cmp r2, #0x4
+ beq _CopyFirmwareSDMMC
+
+
+_CopyFirmwareSDMMC:
+ bl ASM_PFX(CopyFirmwareFromSDMMC)
+ b _PrepareArguments
+
+_CopyFirmwareEMMC:
+ bl ASM_PFX(CopyFirmwareFromEMMC)
+ b _PrepareArguments
+
+_ColdBootTzsw:
+ bl ASM_PFX(ColdBootForTzsw)
+_NeverReturn:
+ b _NeverReturn
+
+
+/*
+ * relocate_code: load NonSecure code(cpu1_wait)
+ */
+relocate_code:
+ adr r0, nscode_base @ r0: source address (start)
+ adr r1, nscode_end @ r1: source address (end)
+ ldr r2, =CONFIG_PHY_IRAM_NS_BASE @ r2: target address
+
+1:
+ ldmia r0!, {r3-r6}
+ stmia r2!, {r3-r6}
+ cmp r0, r1
+ blt 1b
+
+ .word 0xF57FF04F @dsb sy
+ .word 0xF57FF06F @isb sy
+
+ mov pc, lr
+
+/*
+ * CPU1 waits here until CPU0 wake it up.
+ * - below code is copied to CONFIG_PHY_IRAM_NS_BASE, which is non-secure memory.
+ */
+nscode_base:
+ adr r0, _ns_reg5
+ b 1f
+
+ .word 0x0 @ REG0: RESUME_ADDR
+ .word 0x0 @ REG1: RESUME_FLAG
+ .word 0x0 @ REG2
+ .word 0x0 @ REG3
+ .word 0x0 @ REG4
+_ns_reg5:
+ .word 0x0 @ REG5: CPU1_BOOT_REG
+ .word 0x0 @ REG6: REG_DIRECTGO_FLAG
+ .word 0x0 @ REG7: REG_DIRECTGO_ADDR
+ .word 0x0 @ REG8
+ .word 0x0 @ REG9
+
+ nop
+ nop
+
+1:
+#if 0 /* Exynos5250 do not require this code */
+ mrc p15, 0, r1, c0, c0, 5 @ MPIDR
+ and r1, r1, #0x3
+ add r0, r0, r1, lsl #0x2
+#endif
+cpu1_wait:
+ .word 0xE320F002 @ wfe instruction
+ ldr r1, [r0]
+ cmp r1, #0x0
+ bxne r1
+ b cpu1_wait
+ nop
+nscode_end:
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecEntryPoint.asm b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecEntryPoint.asm
new file mode 100644
index 000000000..07ad1289b
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecEntryPoint.asm
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 2011-2012, 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 <AutoGen.h>
+#include <AsmMacroIoLib.h>
+#include "SecInternal.h"
+
+ INCLUDE AsmMacroIoLib.inc
+
+ IMPORT CEntryPoint
+ IMPORT ArmPlatformSecBootAction
+ IMPORT ArmPlatformSecBootMemoryInit
+ IMPORT ArmDisableInterrupts
+ IMPORT ArmDisableCachesAndMmu
+ IMPORT ArmReadMpidr
+ IMPORT ArmCallWFE
+ EXPORT _ModuleEntryPoint
+
+ PRESERVE8
+ AREA SecEntryPoint, CODE, READONLY
+
+StartupAddr DCD CEntryPoint
+
+_ModuleEntryPoint
+ // First ensure all interrupts are disabled
+ blx ArmDisableInterrupts
+
+ // Ensure that the MMU and caches are off
+ blx ArmDisableCachesAndMmu
+
+ // Jump to Platform Specific Boot Action function
+ blx ArmPlatformSecBootAction
+
+_IdentifyCpu
+ // Identify CPU ID
+ bl ArmReadMpidr
+ // Get ID of this CPU in Multicore system
+ LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCoreMask), r1)
+ and r5, r0, r1
+
+ // Is it the Primary Core ?
+ LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCore), r3)
+ cmp r5, r3
+ // Only the primary core initialize the memory (SMC)
+ beq _InitMem
+
+_WaitInitMem
+ // Wait for the primary core to initialize the initial memory (event: BOOT_MEM_INIT)
+ bl ArmCallWFE
+ // Now the Init Mem is initialized, we setup the secondary core stacks
+ b _SetupSecondaryCoreStack
+
+_InitMem
+ // Initialize Init Boot Memory
+ bl ArmPlatformSecBootMemoryInit
+
+ // Only Primary CPU could run this line (the secondary cores have jumped from _IdentifyCpu to _SetupStack)
+ LoadConstantToReg (FixedPcdGet32(PcdArmPrimaryCore), r5)
+
+_SetupPrimaryCoreStack
+ // Get the top of the primary stacks (and the base of the secondary stacks)
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r1)
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecPrimaryStackSize), r2)
+ add r1, r1, r2
+
+ LoadConstantToReg (FixedPcdGet32(PcdSecGlobalVariableSize), r2)
+
+ // The reserved space for global variable must be 8-bytes aligned for pushing
+ // 64-bit variable on the stack
+ SetPrimaryStack (r1, r2, r3)
+ b _PrepareArguments
+
+_SetupSecondaryCoreStack
+ // Get the top of the primary stacks (and the base of the secondary stacks)
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoresSecStackBase), r1)
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecPrimaryStackSize), r2)
+ add r1, r1, r2
+
+ // Get the Core Position (ClusterId * 4) + CoreId
+ GetCorePositionInStack(r0, r5, r2)
+ // The stack starts at the top of the stack region. Add '1' to the Core Position to get the top of the stack
+ add r0, r0, #1
+
+ // StackOffset = CorePos * StackSize
+ LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecSecondaryStackSize), r2)
+ mul r0, r0, r2
+ // SP = StackBase + StackOffset
+ add sp, r1, r0
+
+_PrepareArguments
+ // Move sec startup address into a data register
+ // Ensure we're jumping to FV version of the code (not boot remapped alias)
+ ldr r3, StartupAddr
+
+ // Jump to SEC C code
+ // r0 = mp_id
+ mov r0, r5
+ blx r3
+
+_NeverReturn
+ b _NeverReturn
+ END
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecFromTzsw.S b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecFromTzsw.S
new file mode 100644
index 000000000..aa6a896c9
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecFromTzsw.S
@@ -0,0 +1,13 @@
+
+.text
+
+GCC_ASM_IMPORT(CEntryPoint)
+GCC_ASM_EXPORT(_SecEntryFromTzsw)
+
+StartupAddr: .word ASM_PFX(CEntryPoint)
+
+ASM_PFX(_SecEntryFromTzsw):
+ mov r0, #0
+ ldr r3, StartupAddr
+ blx r3
+
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecInternal.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecInternal.h
new file mode 100644
index 000000000..eff157a64
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/SecInternal.h
@@ -0,0 +1,75 @@
+/** @file
+* Main file supporting the SEC Phase on ARM PLatforms
+*
+* Copyright (c) 2011-2012, 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 __SEC_H__
+#define __SEC_H__
+
+#include <Base.h>
+#include <Library/ArmLib.h>
+#include <Library/ArmCpuLib.h>
+#include <Library/ArmPlatformSecLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <ArmPlatform.h>
+
+#define IS_ALIGNED(Address, Align) (((UINTN)Address & (Align-1)) == 0)
+
+VOID
+TrustedWorldInitialization (
+ IN UINTN MpId
+ );
+
+VOID
+NonTrustedWorldTransition (
+ IN UINTN MpId,
+ IN UINTN JumpAddress
+ );
+
+VOID
+ArmSetupGicNonSecure (
+ IN INTN GicDistributorBase,
+ IN INTN GicInterruptInterfaceBase
+);
+
+VOID
+enter_monitor_mode (
+ IN UINTN MonitorEntryPoint,
+ IN UINTN MpId,
+ IN VOID* Stack
+ );
+
+VOID
+return_from_exception (
+ IN UINTN NonSecureBase
+ );
+
+VOID
+copy_cpsr_into_spsr (
+ VOID
+ );
+
+VOID
+set_non_secure_mode (
+ IN ARM_PROCESSOR_MODE Mode
+ );
+
+VOID
+SecCommonExceptionEntry (
+ IN UINT32 Entry,
+ IN UINT32 LR
+ );
+
+#endif
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Smc.c b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Smc.c
new file mode 100644
index 000000000..3de899a11
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Smc.c
@@ -0,0 +1,110 @@
+/** @file
+* Main file supporting the SMC call on ARM Platforms
+*
+* Copyright (c) 2011-2012, 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 "Smc.h"
+
+#define SMC_CMD_LOAD_UEFI (-230)
+#define SMC_CMD_COLDBOOT (-231)
+#define SMC_CMD_WARMBOOT (-232)
+
+#define SIGNATURE_SIZE 0
+
+#define MOVI_BLKSIZE (1 << 9)
+#define PART_SIZE_UEFI (2560 * 1024)
+#define PART_SIZE_TZSW (156 * 1024)
+#define MOVI_UEFI_BLKCNT (PART_SIZE_UEFI / MOVI_BLKSIZE)
+#define MOVI_TZSW_BLKCNT (PART_SIZE_TZSW / MOVI_BLKSIZE)
+
+typedef struct sdmmc_dev {
+ /* for SDMMC */
+ UINT32 image_pos;
+ UINT32 blkcnt;
+ UINT32 base_addr;
+} sdmmc_t;
+
+typedef struct emmc_dev {
+ /* for eMMC */
+ UINT32 blkcnt;
+ UINT32 base_addr;
+} emmc_t;
+
+/* boot device */
+typedef union boot_device_u {
+ sdmmc_t sdmmc;
+ emmc_t emmc;
+} boot_device_t;
+
+typedef struct ld_image_info {
+ UINT32 image_base_addr;
+ UINT32 size;
+ UINT32 secure_context_base;
+ UINT32 signature_size;
+ boot_device_t bootdev;
+} image_info;
+
+UINT32 exynos_smc(UINT32 cmd, UINT32 arg1, UINT32 arg2, UINT32 arg3)
+{
+ register UINT32 reg0 __asm__("r0") = cmd;
+ register UINT32 reg1 __asm__("r1") = arg1;
+ register UINT32 reg2 __asm__("r2") = arg2;
+ register UINT32 reg3 __asm__("r3") = arg3;
+
+ __asm__ volatile (
+ ".arch_extension sec\n"
+ "smc 0\n"
+ : "+r"(reg0), "+r"(reg1), "+r"(reg2), "+r"(reg3)
+
+ );
+
+ return reg0;
+}
+
+void load_uefi_image(UINT32 boot_device)
+{
+ image_info *info_image;
+
+ info_image = (image_info *) CONFIG_IMAGE_INFO_BASE;
+
+ if (boot_device == EMMC) {
+ info_image->bootdev.emmc.blkcnt = MOVI_UEFI_BLKCNT;
+ info_image->bootdev.emmc.base_addr = CONFIG_PHY_UEFI_BASE;
+ }
+
+ info_image->image_base_addr = CONFIG_PHY_UEFI_BASE;
+ info_image->size = (MOVI_UEFI_BLKCNT * MOVI_BLKSIZE);
+ info_image->secure_context_base = CONFIG_SECURE_CONTEXT_BASE;
+ info_image->signature_size = SIGNATURE_SIZE;
+
+ exynos_smc(SMC_CMD_LOAD_UEFI, boot_device, CONFIG_IMAGE_INFO_BASE, 0);
+}
+
+void coldboot(UINT32 boot_device, UINT32 JumpAddress)
+{
+ image_info *info_image;
+
+ info_image = (image_info *) CONFIG_IMAGE_INFO_BASE;
+
+ if (boot_device == EMMC) {
+ info_image->bootdev.emmc.blkcnt = MOVI_TZSW_BLKCNT;
+ info_image->bootdev.emmc.base_addr = CONFIG_PHY_TZSW_BASE;
+ }
+
+ info_image->image_base_addr = CONFIG_PHY_TZSW_BASE;
+ info_image->size = (MOVI_TZSW_BLKCNT * MOVI_BLKSIZE);
+ info_image->secure_context_base = CONFIG_SECURE_CONTEXT_BASE;
+ info_image->signature_size = SIGNATURE_SIZE;
+
+ exynos_smc(SMC_CMD_COLDBOOT, boot_device, CONFIG_IMAGE_INFO_BASE, JumpAddress);
+}
diff --git a/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Smc.h b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Smc.h
new file mode 100644
index 000000000..1dcb1ac79
--- /dev/null
+++ b/SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Smc.h
@@ -0,0 +1,60 @@
+/** @file
+* Header file supporting the SMC call on ARM Platforms
+*
+* Copyright (c) 2011-2012, 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 __SMC_H__
+#define __SMC_H__
+
+#include <Platform/ArmPlatform.h>
+
+/* Boot Device */
+#define SDMMC_CH2 0x0
+#define SDMMC_CH0 0x4
+#define EMMC 0x14
+
+/* SMC call define */
+#define SMC_CMD_INIT (-1)
+#define SMC_CMD_INFO (-2)
+/* For Power Management */
+#define SMC_CMD_SLEEP (-3)
+#define SMC_CMD_CPU1BOOT (-4)
+#define SMC_CMD_CPU0AFTR (-5)
+/* For CP15 Access */
+#define SMC_CMD_C15RESUME (-11)
+/* For L2 Cache Access */
+#define SMC_CMD_L2X0CTRL (-21)
+#define SMC_CMD_L2X0SETUP1 (-22)
+#define SMC_CMD_L2X0SETUP2 (-23)
+#define SMC_CMD_L2X0INVALL (-24)
+#define SMC_CMD_L2X0DEBUG (-25)
+
+/* For Accessing CP15/SFR (General) */
+#define SMC_CMD_REG (-101)
+
+/* MACRO for SMC_CMD_REG */
+#define SMC_REG_CLASS_CP15 (0x0 << 30)
+#define SMC_REG_CLASS_SFR_W (0x1 << 30)
+#define SMC_REG_CLASS_SFR_R (0x3 << 30)
+#define SMC_REG_CLASS_MASK (0x3 << 30)
+#define SMC_REG_ID_CP15(CRn, Op1, CRm, Op2) \
+ (SMC_REG_CLASS_CP15 | \
+ ((CRn) << 10) | ((Op1) << 7) | ((CRm) << 3) | (Op2))
+#define SMC_REG_ID_SFR_W(ADDR) (SMC_REG_CLASS_SFR_W | ((ADDR) >> 2))
+#define SMC_REG_ID_SFR_R(ADDR) (SMC_REG_CLASS_SFR_R | ((ADDR) >> 2))
+
+void load_uefi_image(UINT32 boot_device);
+void coldboot(UINT32 boot_device, UINT32 JumpAddress);
+UINT32 exynos_smc(UINT32 cmd, UINT32 arg1, UINT32 arg2, UINT32 arg3);
+
+#endif /* __SMC_H__ */