diff options
author | Steven Kinney <steven.kinney@linaro.org> | 2013-11-08 13:41:13 -0600 |
---|---|---|
committer | Steven Kinney <steven.kinney@linaro.org> | 2013-11-08 13:41:13 -0600 |
commit | d5836c2a5e7d7eb8a7c637af2bcbe33c2a761ffa (patch) | |
tree | f32cb5db0f8e3e7250a3eb273c5fdea4fdf58009 | |
parent | e0cec187231a1bf8fc12caa0c4f734771cf6fe42 (diff) | |
parent | 4c5367d2e2e9426f8dbdf302456df6bef9cb7c86 (diff) |
Merge branch 'linaro-topic-arndale' into linaro-tracking-2013.11
159 files changed, 36464 insertions, 0 deletions
diff --git a/SamsungPlatformPkg/Apps/Ebl.efi b/SamsungPlatformPkg/Apps/Ebl.efi Binary files differnew file mode 100644 index 000000000..a5d637329 --- /dev/null +++ b/SamsungPlatformPkg/Apps/Ebl.efi diff --git a/SamsungPlatformPkg/Apps/TestApps/HashServicesTest/HashServicesTest.c b/SamsungPlatformPkg/Apps/TestApps/HashServicesTest/HashServicesTest.c new file mode 100644 index 000000000..b5b46dc7f --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/HashServicesTest/HashServicesTest.c @@ -0,0 +1,54 @@ +#include <Uefi.h> + +#include <Library/UefiLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiApplicationEntryPoint.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UncachedMemoryAllocationLib.h> + +#include <Protocol/Hash.h> +#include <Protocol/PciIo.h> + +#define NOT_EXTEND 0 +#define EXTEND 1 + +#define TEST_HASH 0x12345678 + +EFI_STATUS +EFIAPI +HashTestMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + EFI_HASH_PROTOCOL *HashProtocol; + UINTN HashSize; + UINT8 *Message; + UINT32 Count, Test[5]; + EFI_HASH_OUTPUT *Hash; + + DEBUG((EFI_D_ERROR, "[HashTestApps] : HashTestApps\n")); + + for (Count = 0 ; Count < 5; Count++) + Test[Count] = TEST_HASH; + + Status = gBS->LocateProtocol(&gEfiHashProtocolGuid, NULL, (VOID **)&HashProtocol); + ASSERT_EFI_ERROR(Status); + + HashProtocol->GetHashSize(HashProtocol, &gEfiHashAlgorithmSha1Guid, &HashSize); + + Message = (UINT8 *)UncachedAllocatePool(HashSize); + Hash = (EFI_HASH_OUTPUT *)UncachedAllocatePool(sizeof(EFI_HASH_OUTPUT)); + + gBS->CopyMem(Hash, Test, sizeof(EFI_SHA1_HASH)); + gBS->CopyMem(Message, "abc", sizeof("abc")); + + HashProtocol->Hash(HashProtocol, &gEfiHashAlgorithmSha1Guid, EXTEND, Message, (UINT64)sizeof("abc"), Hash); + + DEBUG((EFI_D_ERROR, "[HashResult] : Result = %x\n", (EFI_SHA1_HASH *)Hash->Sha1Hash)); + + return Status; +} + diff --git a/SamsungPlatformPkg/Apps/TestApps/HashServicesTest/HashServicesTest.inf b/SamsungPlatformPkg/Apps/TestApps/HashServicesTest/HashServicesTest.inf new file mode 100644 index 000000000..76b155479 --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/HashServicesTest/HashServicesTest.inf @@ -0,0 +1,46 @@ +## @file HashServicesTest.inf +# +# Samsung S.LSI HashServicesTest application +# +# Copyright (c) 2012-2013, Samsung Electronics Inc. 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 = HashServicesTest + FILE_GUID = 95434237-90a5-4cb2-85ff-2300be4520de + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = HashTestMain + +[Sources] + HashServicesTest.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec + SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UncachedMemoryAllocationLib + UefiLib + PcdLib + DebugLib + +[Protocols] + gEfiHashProtocolGuid + gEfiPciIoProtocolGuid + +[Guids] + gEfiHashAlgorithmSha1Guid + gEfiHashAlgorithmSha256Guid diff --git a/SamsungPlatformPkg/Apps/TestApps/MiscellaneousServicesTest/MiscellaneousServicesTest.c b/SamsungPlatformPkg/Apps/TestApps/MiscellaneousServicesTest/MiscellaneousServicesTest.c new file mode 100644 index 000000000..ac97c5e44 --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/MiscellaneousServicesTest/MiscellaneousServicesTest.c @@ -0,0 +1,143 @@ +/** @file MiscellaneousTest.c + + Samsung S.LSI MiscellaneousServices application + + Copyright (c) 2012-2013, Samsung Electronics Inc. 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. + +**/ + +/*============================================================================= + EDIT HISTORY + + DateTime: 2012/01/31 + Author: Jang Young Gun : yg1004.jang@samsung.com + + when who what, where, why + -------- --- ----------------------------------------------------------- + 01/31/12 yg.jang Initial revision + +=============================================================================*/ + +#include <Uefi.h> +#include <Library/PcdLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> + +EFI_EVENT HelloTimerEvent; + +VOID +EFIAPI print_hello( void ) +{ + UINT32 Index; + + Index = 0; + + // + // Three PCD type (FeatureFlag, UINT32 and String) are used as the sample. + // + if (FeaturePcdGet (PcdHelloWorldPrintEnable)) { + for (Index = 0; Index < PcdGet32 (PcdHelloWorldPrintTimes); Index ++) { + // + // Use UefiLib Print API to print string to UEFI console + // + Print ((CHAR16*)PcdGetPtr (PcdHelloWorldPrintString)); + } + } +} + +/** + The user Entry Point for Application. The user code starts with this function + as the real entry point for the application. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN EventIndex; + EFI_STATUS Status; + UINT64 BSCounter; + UINT64 BSCounterNext; + UINT32 RTCounter; + UINT32 RTCounterNext; + + do{ + print_hello(); + + // + // Create the timer event to implement a timer + // + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_NOTIFY, + NULL, + NULL, + &HelloTimerEvent + ); + if(EFI_ERROR (Status)) { + break; + } + + // Set timer for 1 second + AsciiPrint("Registering Timer Event: 1 second relative timer\n"); + gBS->SetTimer(HelloTimerEvent, TimerRelative, 10000000); + AsciiPrint("Waiting for 1 second\n"); + gBS->WaitForEvent(1, &HelloTimerEvent, &EventIndex); + AsciiPrint("1 second timer event signaled\n"); + + // Test Stall + AsciiPrint("Stalling for 2 seconds\n"); + gBS->Stall(2000000); + AsciiPrint("2 second stall complete\n"); + + // Testing GetNextMonotonicCount + gBS->GetNextMonotonicCount(&BSCounter); + AsciiPrint("Current Monotonic Counter Value: 0x%llx\n", BSCounter); + gBS->GetNextMonotonicCount(&BSCounterNext); + AsciiPrint("Next Monotonic Counter Value: 0x%llx\n", BSCounterNext); + if (BSCounter != (BSCounterNext-1)) + { + Status = EFI_UNSUPPORTED; + break; + } + else + { + AsciiPrint("Monotonic Counter Test Case Passed\n"); + } + + // Testing GetNextHighMonotonicCount + gRT->GetNextHighMonotonicCount(&RTCounter); + AsciiPrint("Current High Monotonic Counter Value: 0x%x\n", RTCounter); + gRT->GetNextHighMonotonicCount(&RTCounterNext); + AsciiPrint("Next High Monotonic Counter Value: 0x%x\n", RTCounterNext); + if (RTCounter != (RTCounterNext-1)) + { + Status = EFI_UNSUPPORTED; + break; + } + else + { + AsciiPrint("High Monotonic Counter Test Case Passed\n"); + } + }while (0); + + return Status; +} diff --git a/SamsungPlatformPkg/Apps/TestApps/MiscellaneousServicesTest/MiscellaneousServicesTest.inf b/SamsungPlatformPkg/Apps/TestApps/MiscellaneousServicesTest/MiscellaneousServicesTest.inf new file mode 100644 index 000000000..fedf51e88 --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/MiscellaneousServicesTest/MiscellaneousServicesTest.inf @@ -0,0 +1,65 @@ +## @file MiscellaneousServicesTest.inf +# +# Samsung S.LSI MiscellaneousServices application +# +# Copyright (c) 2012-2013, Samsung Electronics Inc. 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. +# +## + +#============================================================================== +# EDIT HISTORY +# +# DateTime: 2012/01/31 +# Author: Jang Young Gun : yg1004.jang@samsung.com +# +# when who what, where, why +# -------- --- ---------------------------------------------------------- +# 01/31/12 yg.jang Initial revision +# +#============================================================================== + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MiscellaneousServicesTest + FILE_GUID = C5066246-9923-4A7C-BA7B-453D7241AF75 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = ARM +# + +[Sources] + MiscellaneousServicesTest.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + PcdLib + +[Guids] + +[Ppis] + +[Protocols] + +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintString || PcdHelloWorldPrintEnable ## Valid when gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable + gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintTimes || PcdHelloWorldPrintEnable ## Valid when gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintEnable + diff --git a/SamsungPlatformPkg/Apps/TestApps/RngServicesTest/RngServicesTest.c b/SamsungPlatformPkg/Apps/TestApps/RngServicesTest/RngServicesTest.c new file mode 100644 index 000000000..8bf0dce13 --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/RngServicesTest/RngServicesTest.c @@ -0,0 +1,56 @@ +/** @file + Application for Pseudorandom Number Generator Validation. + +Copyright (c) 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 <Uefi.h> + +#include <Library/DebugLib.h> +#include <Library/UefiApplicationEntryPoint.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UncachedMemoryAllocationLib.h> + +#include <Protocol/ExynosRng.h> + +#define RANDOM_DATA_SIZE 32 /* Bytes */ + +/** + * Validate UEFI pseudorandom number generator + +**/ +EFI_STATUS +EFIAPI +RngTestMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + BOOLEAN Status = EFI_SUCCESS; + UINT8 *RandomData; + UINT32 count; + EFI_RNG_PROTOCOL *RngProtocol; + + DEBUG((EFI_D_ERROR, "UEFI pseudorandom number generator.\n")); + DEBUG((EFI_D_ERROR, "Random Generation...\n\n")); + + RandomData = (UINT8 *)UncachedAllocatePool(RANDOM_DATA_SIZE); + + Status = gBS->LocateProtocol(&gSamsungPlatformRngProtocolGuid, NULL, (VOID **)&RngProtocol); + + RngProtocol->RandomBytes(RngProtocol, RandomData, RANDOM_DATA_SIZE); + + for (count = 0; count < (RANDOM_DATA_SIZE >> 2); count++) + DEBUG((EFI_D_ERROR, "RandomData[%d] : %x\n", count, *(UINT32 *)((UINT32)RandomData + (count << 2)))); + + return Status; +} diff --git a/SamsungPlatformPkg/Apps/TestApps/RngServicesTest/RngServicesTest.inf b/SamsungPlatformPkg/Apps/TestApps/RngServicesTest/RngServicesTest.inf new file mode 100644 index 000000000..02ea76b82 --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/RngServicesTest/RngServicesTest.inf @@ -0,0 +1,41 @@ +## @file RngServicesTest.inf +# +# Samsung S.LSI TimeServicesTest application +# +# Copyright (c) 2012-2013, Samsung Electronics Inc. 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 = RngServicesTest + FILE_GUID = 538b842d-61e3-443a-b68a-fb6901d74fae + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + + ENTRY_POINT = RngTestMain + +[Sources] + RngServicesTest.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec + SamsungPlatformPkg/SamsungPlatformPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UncachedMemoryAllocationLib + UefiLib + DebugLib + +[Protocols] + gSamsungPlatformRngProtocolGuid diff --git a/SamsungPlatformPkg/Apps/TestApps/TimeServicesTest/TimeServicesTest.c b/SamsungPlatformPkg/Apps/TestApps/TimeServicesTest/TimeServicesTest.c new file mode 100644 index 000000000..7e3856c81 --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/TimeServicesTest/TimeServicesTest.c @@ -0,0 +1,156 @@ +/** @file TimeServicesTest.c + + Samsung S.LSI TimeServicesTest application + + Copyright (c) 2012-2013, Samsung Electronics Inc. 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. + +**/ + +/*============================================================================= + EDIT HISTORY + + DateTime: 2012/01/31 + Author: Jang Young Gun : yg1004.jang@samsung.com + + when who what, where, why + -------- --- ----------------------------------------------------------- + 01/31/12 yg.jang Initial revision + +=============================================================================*/ + +#include <Uefi.h> +#include <Library/PcdLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/DebugLib.h> + + +/** Various constant values defined for testing. +*/ +UINT16 test_year = 2011; +UINT8 test_month = 5; +UINT8 test_day = 1; +UINT8 test_minute = 4; +UINT8 test_hour = 3; +UINT8 test_second = 6; +UINT32 test_nanosecond = 0; +UINT16 test_timezone = 7; +UINT8 test_daylight = 0; + +/** We test via stalling a defined amount in the seconds. +*/ +#define STALL_AMOUNT_SECONDS 4 +#define LOWER_BOUND_SECONDS_TEST STALL_AMOUNT_SECONDS - 1 +#define UPPER_BOUND_SECONDS_TEST STALL_AMOUNT_SECONDS + 1 + +/** Convert seconds into an amount the gBS->Stall function will + accept. +*/ +#define CONVERSION_FACTOR_GBS_STALL 1000000 + +/** + The user Entry Point for Application. The user code starts with this function + as the real entry point for the application. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ + +EFI_STATUS +EFIAPI +RTCTestMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_TIME time; + EFI_TIME_CAPABILITIES time_capabilities; + + BOOLEAN tests_passed = TRUE; + + time.Day = test_day; + time.Daylight = test_daylight; + time.Hour = test_hour; + time.Minute = test_minute; + time.Month = test_month; + time.Nanosecond = test_nanosecond; + time.Second = test_second; + time.TimeZone = test_timezone; + time.Year = test_year; + + + AsciiPrint("Setting RTC time to a static value\n"); + Status = gRT->SetTime(&time); + if (Status != EFI_SUCCESS) { + tests_passed = FALSE; + AsciiPrint("Fatal error during test\n"); + return Status; + } + AsciiPrint("Stalling for %d seconds to test incrementation\n", STALL_AMOUNT_SECONDS); + Status = gBS->Stall( (STALL_AMOUNT_SECONDS * CONVERSION_FACTOR_GBS_STALL) ); + if (Status != EFI_SUCCESS) { + tests_passed = FALSE; + AsciiPrint("Fatal error during test\n"); + return Status; + } + AsciiPrint("Getting RTC Time with capabilities\n"); + Status = gRT->GetTime(&time, &time_capabilities); + if (Status != EFI_SUCCESS) { + tests_passed = FALSE; + AsciiPrint("Fatal error during test\n"); + return Status; + } + AsciiPrint("Getting RTC Time without capabilities\n"); + Status = gRT->GetTime(&time, NULL); + if (Status != EFI_SUCCESS) { + tests_passed = FALSE; + AsciiPrint("Failure during test\n"); + return Status; + } + + AsciiPrint("Now displaying deviations\n"); + if ((time.Day - test_day != 0)) { + AsciiPrint("Deviation in DAY of %d days\n", time.Day - test_day); + tests_passed = FALSE; + } + if ((time.Hour - test_hour != 0)) { + AsciiPrint("Deviation in HOUR of %d hours\n", time.Hour - test_hour); + tests_passed = FALSE; + } + if ((time.Minute - test_minute != 0)) { + AsciiPrint("Deviation in MINUTE of %d minutes\n", time.Minute - test_minute); + tests_passed = FALSE; + } + + if ((time.Second - test_second ) > UPPER_BOUND_SECONDS_TEST || + (time.Second - test_second ) < LOWER_BOUND_SECONDS_TEST) { + AsciiPrint("Deviation in SECOND of %d seconds\n", time.Second - test_second); + tests_passed = FALSE; + } + if ((time.Year - test_year != 0)) { + AsciiPrint("Deviation in YEAR of %d years\n", time.Year - test_year); + tests_passed = FALSE; + } + AsciiPrint("Finished displaying deviations\n"); + if (tests_passed) { + AsciiPrint("All tests completed successfully\n"); + } + else{ + AsciiPrint("Not all tests passed. Please see the deviations above.\n"); + } + return Status; +} diff --git a/SamsungPlatformPkg/Apps/TestApps/TimeServicesTest/TimeServicesTest.inf b/SamsungPlatformPkg/Apps/TestApps/TimeServicesTest/TimeServicesTest.inf new file mode 100644 index 000000000..e85e1485a --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/TimeServicesTest/TimeServicesTest.inf @@ -0,0 +1,52 @@ +## @file TimeServicesTest.inf +# +# Samsung S.LSI TimeServicesTest application +# +# Copyright (c) 2012-2013, Samsung Electronics Inc. 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. +# +## + +#============================================================================== +# EDIT HISTORY +# +# DateTime: 2012/01/31 +# Author: Jang Young Gun : yg1004.jang@samsung.com +# +# when who what, where, why +# -------- --- ---------------------------------------------------------- +# 01/31/12 yg.jang Initial revision +# +#============================================================================== + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TimeServicesTest + FILE_GUID = 6E0B9EAA-23E8-4157-A3C0-6A74888EFDA5 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = RTCTestMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = ARM +# + +[Sources] + TimeServicesTest.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + PcdLib + DebugLib diff --git a/SamsungPlatformPkg/Apps/TestApps/VariableServicesTestNonSec/VariableServicesTestNonSec.c b/SamsungPlatformPkg/Apps/TestApps/VariableServicesTestNonSec/VariableServicesTestNonSec.c new file mode 100644 index 000000000..c2d079448 --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/VariableServicesTestNonSec/VariableServicesTestNonSec.c @@ -0,0 +1,193 @@ +/** @file VariableServicesTestNonSec.c + + If the Variable services have PcdVariableCollectStatistics set to TRUE then + the EFI system table will contain statistical information about variable usage + an this utility will print out the information. You can use console redirection + to capture the data. + + Copyright (c) 2012 - 2013, Samsung Electronics 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. + +**/ + +/*============================================================================= + EDIT HISTORY + + DateTime: 2012/01/31 + Author: Jang Young Gun : yg1004.jang@samsung.com + + when who what, where, why + -------- --- ----------------------------------------------------------- + 01/31/12 yg.jang Initial revision + +=============================================================================*/ + +#include <Uefi.h> +#include <Library/UefiLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/UefiApplicationEntryPoint.h> +#include <Guid/VariableFormat.h> + + +/** + The user Entry Point for Application. The user code starts with this function + as the real entry point for the image goes into a library that calls this + function. + + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VARIABLE_INFO_ENTRY *VariableInfo; + VARIABLE_INFO_ENTRY *Entry; + + /* For GetNextVariableName */ + UINTN VariableNameBufferSize; + UINTN VariableNameSize; + CHAR16 *VariableName; + UINTN VariableDataBufferSize; + UINTN VariableDataSize; + VOID *VariableData; + EFI_GUID VendorGuid; + UINT32 VariableAttributes; + VOID *NewBuffer; + + VariableNameBufferSize = sizeof (CHAR16); + VariableNameSize = VariableNameBufferSize; + VariableName = AllocateZeroPool (VariableNameSize); + VariableDataBufferSize = 0; + VariableDataSize = 0; + VariableData = NULL; + VariableAttributes = 0; + + Status = EfiGetSystemConfigurationTable (&gEfiVariableGuid, (VOID **)&Entry); + if (!EFI_ERROR (Status) && (Entry != NULL)) { + Print (L"Non-Volatile EFI Variables:\n"); + VariableInfo = Entry; + do { + if (!VariableInfo->Volatile) { + Print ( + L"%g R%03d(%03d) W%03d D%03d:%s\n", + &VariableInfo->VendorGuid, + VariableInfo->ReadCount, + VariableInfo->CacheCount, + VariableInfo->WriteCount, + VariableInfo->DeleteCount, + VariableInfo->Name + ); + } + + VariableInfo = VariableInfo->Next; + } while (VariableInfo != NULL); + + Print (L"Volatile EFI Variables:\n"); + VariableInfo = Entry; + do { + if (VariableInfo->Volatile) { + Print ( + L"%g R%03d(%03d) W%03d D%03d:%s\n", + &VariableInfo->VendorGuid, + VariableInfo->ReadCount, + VariableInfo->CacheCount, + VariableInfo->WriteCount, + VariableInfo->DeleteCount, + VariableInfo->Name + ); + } + VariableInfo = VariableInfo->Next; + } while (VariableInfo != NULL); + + } else { + Print (L"Warning: Variable Dxe driver doesn't enable the feature of statistical information!\n"); + Print (L"If you want to see this info, please:\n"); + Print (L" 1. Set PcdVariableCollectStatistics as TRUE\n"); + Print (L" 2. Rebuild Variable Dxe driver\n"); + Print (L" 3. Run \"VariableInfo\" cmd again\n"); + + } + + Print (L"GetNextVariableName EFI Variables:\n"); + /* Check GetNextVariableName */ + do { + VariableNameSize = VariableNameBufferSize; + Status = gRT->GetNextVariableName( + &VariableNameSize, + VariableName, + &VendorGuid + ); + + if(Status == EFI_BUFFER_TOO_SMALL) { + NewBuffer = AllocatePool (VariableNameSize); + CopyMem (NewBuffer, VariableName, VariableNameBufferSize); + if(VariableName != NULL) { + FreePool (VariableName); + } + VariableName = NewBuffer; + VariableNameBufferSize = VariableNameSize; + + Status = gRT->GetNextVariableName( + &VariableNameSize, + VariableName, + &VendorGuid + ); + } + + if(Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + break; + } + + VariableDataSize = VariableDataBufferSize; + Status = gRT->GetVariable( + VariableName, + &VendorGuid, + &VariableAttributes, + &VariableDataSize, + VariableData + ); + if(Status == EFI_BUFFER_TOO_SMALL) { + if(VariableDataBufferSize != 0) { + FreePool (VariableData); + VariableData = NULL; + VariableDataBufferSize = 0; + } + + VariableData = AllocatePool (VariableDataSize); + + VariableDataBufferSize = VariableDataSize; + + Status = gRT->GetVariable( + VariableName, + &VendorGuid, + &VariableAttributes, + &VariableDataSize, + VariableData + ); + } + + Print (L"%.-35g %.-20s : %X\n", &VendorGuid, VariableName, VariableData); + + } while (Status == EFI_SUCCESS); + + return Status; +} diff --git a/SamsungPlatformPkg/Apps/TestApps/VariableServicesTestNonSec/VariableServicesTestNonSec.inf b/SamsungPlatformPkg/Apps/TestApps/VariableServicesTestNonSec/VariableServicesTestNonSec.inf new file mode 100644 index 000000000..643a2afb2 --- /dev/null +++ b/SamsungPlatformPkg/Apps/TestApps/VariableServicesTestNonSec/VariableServicesTestNonSec.inf @@ -0,0 +1,64 @@ +## @file VariableServicesTestNonSec.inf +# +# Samsung S.LSI VariableServicesTestNonSec application +# +# Sample UEFI Application Reference Module. +# This is a shell application that will display statistical information about variable +# usage. +# Note that if Variable Dxe driver doesnt enable the feature by setting PcdVariableCollectStatistics +# as TRUE, The application will not display variable statistical information. +# +# Copyright (c) 2012-2013, Samsung Electronics Inc. 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. +# +## + +#============================================================================== +# EDIT HISTORY +# +# DateTime: 2012/01/31 +# Author: Jang Young Gun : yg1004.jang@samsung.com +# +# when who what, where, why +# -------- --- ---------------------------------------------------------- +# 01/31/12 yg.jang Initial revision +# +#============================================================================== + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = VariableServicesTestNonSec + FILE_GUID = 202A2922-8C27-4943-9855-26180BF9F113 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + + ENTRY_POINT = UefiMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + VariableServicesTestNonSec.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + + +[LibraryClasses] + UefiApplicationEntryPoint + MemoryAllocationLib + BaseMemoryLib + UefiLib + +[Guids] + gEfiVariableGuid ## CONSUMES ## Configuration Table Guid diff --git a/SamsungPlatformPkg/Apps/Tools/fwupdate/fwupdate.c b/SamsungPlatformPkg/Apps/Tools/fwupdate/fwupdate.c new file mode 100755 index 000000000..70331c3a6 --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/fwupdate/fwupdate.c @@ -0,0 +1,541 @@ +#include <Uefi.h> +#include <Library/PcdLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiApplicationEntryPoint.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/EfiFileLib.h> +#include <Protocol/BlockIo.h> +#include <Protocol/DiskIo.h> + +#define FILE_COPY_CHUNK 0x280000 +#define TZSW_PARTITION_SIZE 0x80000 +#define BLOCK_SIZE 512 +#ifndef MAX_PATH +#define MAX_PATH 128 +#endif + + +/* + * Enumerations for Source type and target device + */ +typedef enum _FW_SOURCE_TYPE { + SOURCE_MEMORY = 1, + SOURCE_FILE = 2 +} FW_SOURCE_TYPE; + +typedef enum _FW_BOOT_DEVICE { + BOOTDEV_MIN = 0, + BOOTDEV_EMMC = 1, + BOOTDEV_SDCARD= 2, + BOOTDEV_MAX = 3 +} FW_BOOT_DEVICE; + + +/* + * Default Settings for FW Update (Moved from PCD) + */ +#define DEFAULT_SOURCE_TYPE SOURCE_MEMORY +#define DEFAULT_TARGET_DEVICE BOOTDEV_EMMC +#define DEFAULT_BL1_SIZE 15 +#define DEFAULT_BL1_SOURCE_ADDRESS 0x42000000 +#define DEFAULT_UEFI_SOURCE_ADDRESS 0x44000000 +#define DEFAULT_TZSW_SOURCE_ADDRESS 0x45000000 +#define DEFAULT_BL1_SOURCE_FILE L"fs1:\\fwbl1_5250.bin" +#define DEFAULT_UEFI_SOURCE_FILE L"fs1:\\ARNDALE_EFI.fd" +#define DEFAULT_TZSW_SOURCE_FILE L"fs1:\\TZSW.bin" + +#define BL2_BLOCK_COUNT 32 + +typedef struct _FW_UPDATE_INFO { + FW_SOURCE_TYPE SourceType; + UINT32 BL1SourceAddr; + UINT32 UEFISourceAddr; + UINT32 TZSWSourceAddr; + CHAR8 BL1FileName[MAX_PATH]; + CHAR8 UefiFileName[MAX_PATH]; + CHAR8 TZSWFileName[MAX_PATH]; + FW_BOOT_DEVICE TargetMediaID; + +} FW_UPDATE_INFO; + + +/* Prototypes of local functions */ +EFI_STATUS GetFirmwareUpdateInfoFromUser( + OUT struct _FW_UPDATE_INFO* pFwUpdateInfo); +VOID SetDefaultFirmwareUpdateInfo( + OUT struct _FW_UPDATE_INFO* pFwUpdateInfo); + + +EFI_STATUS GetHIInputInteger (OUT UINTN *Integer); +EFI_STATUS GetHIInputStr (IN OUT CHAR16 *CmdLine, IN UINTN MaxCmdLine); +EFI_STATUS GetHIInputHex (OUT UINTN *Integer); + +/** + The user Entry Point for Application. The user code starts with this function + as the real entry point for the application. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_OPEN_FILE *Source = NULL; + VOID *Buffer = NULL; + EFI_HANDLE *HandleBuffer = NULL; + EFI_STATUS Status = EFI_SUCCESS; + UINTN Size, NumHandles; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + UINT32 i; + + UINT32 TargetMediaId; + + /* Start block number for writing bootloader blocks - default value is for eMMC*/ + UINT32 BL1TargetBlock = 0; + UINT32 BL2TargetBlock = 16; + UINT32 UEFITargetBlock = 48; + UINT32 TZSWTargetBlock = 5216; // 2608K + + struct _FW_UPDATE_INFO fwUpdateInfo; + + /* Get Firmware update information from User */ + GetFirmwareUpdateInfoFromUser(&fwUpdateInfo); + + /* Set Media ID as user's setting */ + switch (fwUpdateInfo.TargetMediaID) { + case BOOTDEV_EMMC: + TargetMediaId = SIGNATURE_32('e','m','m','c'); + break; + case BOOTDEV_SDCARD: + TargetMediaId = SIGNATURE_32('s','d','h','c'); + BL1TargetBlock += 1; + break; + default: + DEBUG((EFI_D_ERROR, "Target Device is unknown device %d\n", fwUpdateInfo.TargetMediaID)); + return EFI_UNSUPPORTED; + } + + /* Workaround: There's a code that increase MediaID of Block IO device when it found, + Therefore, to match media ID of the device, target Media ID here should be incresed by 1 + This is temporary solution, eventually, Block IO device management code should be modified */ + TargetMediaId ++; + + DEBUG((EFI_D_INFO, "Target Device ID = 0x%x\n", TargetMediaId)); + + /* Locating all handles in the system supporting EFI_BLOCK_IO_PROTOCOL */ + Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &NumHandles, &HandleBuffer); + + DEBUG((EFI_D_INFO, "Number of handles supporting Block IO = %d\n", NumHandles)); + + /* Finding out the handle of the SDHC Block IO driver through its Media ID + i.e. 0x63686473 (The Media ID can be found in the SDHC DXE driver code) */ + for(i=0;i<NumHandles;i++) { + Status = gBS->HandleProtocol(HandleBuffer[i], &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + ASSERT_EFI_ERROR(Status); + + DEBUG((EFI_D_ERROR, "Device %d Media ID=0x%x\n", i, BlockIo->Media->MediaId)); + + if(BlockIo->Media->MediaId == TargetMediaId) + break; + } + + if(i == NumHandles) { + DEBUG((EFI_D_ERROR, "Cannot find Block IO protocol handle! \n")); + goto Exit; + } + + /* Locating the Disk IO handle corresponding to the target device Block IO handle + (Note: There is a Disk IO handle for every Block IO handle according to Disk IO driver implementation) */ + Status = gBS->HandleProtocol(HandleBuffer[i], &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo); + ASSERT_EFI_ERROR(Status); + + /* Allocating 2MB buffer for impending read operations */ + Buffer = AllocatePool(FILE_COPY_CHUNK); + if (Buffer == NULL) { + DEBUG((EFI_D_ERROR, "AllocatePool error.\n")); + goto Exit; + } + + + /* for temporally */ + if (fwUpdateInfo.SourceType == SOURCE_FILE) { + + /* Reading BL1 binary from file system (for example in USB flask disk) into the allocated buffer */ + Source = EfiOpen(fwUpdateInfo.BL1FileName, EFI_FILE_MODE_READ, 0); + if (Source == NULL) { + /* TODO: Convert file name which is written in ASCII string to Unicode to print to console */ + DEBUG((EFI_D_ERROR, "Source file [%s] open error.\n", fwUpdateInfo.BL1FileName)); + return EFI_NOT_FOUND; + } + + Size = EfiTell(Source, NULL); + + DEBUG((EFI_D_ERROR, "File size = %d\n", Size)); + + Status = EfiRead(Source, Buffer, &Size); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Read file error %r\n", Status)); + goto Exit; + } + + Status = EfiClose(Source); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Source file close error %r\n", Status)); + } + Source = NULL; + } else { + if (*((UINT32 *)(fwUpdateInfo.BL1SourceAddr + 0x2000)) == 0xEA000038) + { + Size = 15 * 1024; // 16 KB + DEBUG((EFI_D_ERROR, "Loading BL1 + BLMon (0x%X) (%d) \n", *((UINT32 *)(fwUpdateInfo.BL1SourceAddr + 0x2000)) ,Size)); + } else { + Size = 8 * 1024; + DEBUG((EFI_D_ERROR, "Loading BL1 without BLMon (0x%X) (%d) \n", *((UINT32 *)(fwUpdateInfo.BL1SourceAddr + 0x2000)) ,Size)); + } + gBS->CopyMem(Buffer, (VOID *)fwUpdateInfo.BL1SourceAddr, Size ); + } + + /* Writing BL1 into the SD card starting from block BL1TargetBlock (0 for eMMC, 1 for SD) + i.e. offset -> block no. * block size -> 1 x 512 = 512 */ + Status = DiskIo->WriteDisk(DiskIo, BlockIo->Media->MediaId, (BL1TargetBlock*BLOCK_SIZE), Size, Buffer); + ASSERT_EFI_ERROR(Status); + + + /* BL2 target block should be vary with BL1 size */ + BL2TargetBlock = BL1TargetBlock + (UINT32)((Size-1) / BLOCK_SIZE) + 1; + DEBUG((EFI_D_ERROR, "BL2 Target Block Number is %d\n", BL2TargetBlock)); + + if (fwUpdateInfo.SourceType == SOURCE_FILE) { + + /* Reading the new UEFI F/W binary into the allocated buffer */ + Source = EfiOpen(fwUpdateInfo.UefiFileName, EFI_FILE_MODE_READ, 0); + if (Source == NULL) { + DEBUG((EFI_D_ERROR, "Source file [%s] open error.\n", fwUpdateInfo.UefiFileName)); + return EFI_NOT_FOUND; + } + + Size = EfiTell(Source, NULL); + + DEBUG((EFI_D_ERROR, "File size = %d\n", Size)); + + Status = EfiRead(Source, Buffer, &Size); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Read file error %r\n", Status)); + goto Exit; + } + } else { + Size = FILE_COPY_CHUNK; + gBS->CopyMem( Buffer, (void *) fwUpdateInfo.UEFISourceAddr, Size); + } + + + /* Writing BL2 into the Boot device from BL2 (16 for eMMC, 17 for SD) for upto 32 blocks */ + { + UINT32 checksum, tmp, addr, i; + + addr = (UINT32)Buffer; + + /* Calculating and writing the checksum required for BL2 */ + for(i=0, checksum=0;i<((14*1024) -4);i++) + checksum += *((UINT8 *)addr++); + + tmp = *((UINT32 *)addr); + *((UINT32 *)addr) = checksum; + + Status = DiskIo->WriteDisk(DiskIo, BlockIo->Media->MediaId, (BL2TargetBlock*BLOCK_SIZE), (BL2_BLOCK_COUNT*BLOCK_SIZE), Buffer); + ASSERT_EFI_ERROR(Status); + + *((UINT32 *)addr) = tmp; + } + + + /* UEFI target block should be vary with BL1 size */ + UEFITargetBlock = BL2TargetBlock + BL2_BLOCK_COUNT; + DEBUG((EFI_D_ERROR, "UEFI Target Block Number is %d\n", UEFITargetBlock)); + + /* Finally Writing the new UEFI F/W into the Boot device from UEFITargetBlock (48 for eMMC, 49 for SD) */ + Status = DiskIo->WriteDisk(DiskIo, BlockIo->Media->MediaId, (UEFITargetBlock*BLOCK_SIZE), Size, Buffer); + ASSERT_EFI_ERROR(Status); + + + if (fwUpdateInfo.SourceType == SOURCE_FILE) { + + /* Reading the new UEFI F/W binary into the allocated buffer */ + Source = EfiOpen(fwUpdateInfo.TZSWFileName, EFI_FILE_MODE_READ, 0); + if (Source == NULL) { + DEBUG((EFI_D_ERROR, "Source file [%s] open error.\n", fwUpdateInfo.TZSWFileName)); + return EFI_NOT_FOUND; + } + + Size = EfiTell(Source, NULL); + + DEBUG((EFI_D_ERROR, "File size = %d\n", Size)); + + Status = EfiRead(Source, Buffer, &Size); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Read file error %r\n", Status)); + goto Exit; + } + } else { + Size = TZSW_PARTITION_SIZE; + gBS->CopyMem( Buffer, (void *) fwUpdateInfo.TZSWSourceAddr, Size); + } + + + TZSWTargetBlock = UEFITargetBlock + ((FILE_COPY_CHUNK-1) / BLOCK_SIZE) + 1; + DEBUG((EFI_D_ERROR, "TZSW Target Block Number is %d\n", TZSWTargetBlock)); + + Status = DiskIo->WriteDisk(DiskIo, BlockIo->Media->MediaId, (TZSWTargetBlock * BLOCK_SIZE), Size, Buffer); + ASSERT_EFI_ERROR(Status); + +Exit: + if (Source != NULL) { + Status = EfiClose(Source); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Source file close error %r\n", Status)); + } + } + + if (Buffer != NULL) { + FreePool(Buffer); + } + + return Status; +} + + + +/** + Get required parameters such as firmware image file name and target device from the user + + @param[out] pFwUpdateInfo Pointer to a structure that has firmware update information + + @retval EFI_SUCCESS This function is executed successfully + @retval other Some error occurs while executing this function + +**/ + +EFI_STATUS +GetFirmwareUpdateInfoFromUser( + OUT struct _FW_UPDATE_INFO* pFwUpdateInfo + ) +{ + UINT32 TargetMediaId; + UINT32 nInput; + CHAR16 InputFileName[MAX_PATH]; + + + + SetDefaultFirmwareUpdateInfo(pFwUpdateInfo); + + + /* Derek - 2012. 7. 10 */ + // Ask to user about Update image source + Print(L"Select your update image source location (1: Memory , 2: File) (%d):", pFwUpdateInfo->SourceType); + GetHIInputInteger(&nInput); + if( (nInput == 1) || (nInput == 2) ) + pFwUpdateInfo->SourceType = nInput; + + if (pFwUpdateInfo->SourceType == SOURCE_MEMORY) { + Print(L"Enter BL1 Source Address (0x%08X) : 0x", pFwUpdateInfo->BL1SourceAddr); + GetHIInputHex(&nInput); + if (nInput) + pFwUpdateInfo->BL1SourceAddr = nInput; + + Print(L"Enter UEFI Source address (0x%08X) : 0x", pFwUpdateInfo->UEFISourceAddr); + GetHIInputHex(&nInput); + if (nInput) + pFwUpdateInfo->UEFISourceAddr = nInput; + + Print(L"Enter TZSW Source address (0x%08X) : 0x", pFwUpdateInfo->TZSWSourceAddr); + GetHIInputHex(&nInput); + if (nInput) + pFwUpdateInfo->TZSWSourceAddr = nInput; + + } else { // Source type is File + + Print(L"Enter BL1 Image File Name (%a):",pFwUpdateInfo->BL1FileName); + + GetHIInputStr(InputFileName, MAX_PATH); + if (StrLen (InputFileName) > 0) + UnicodeStrToAsciiStr(InputFileName, pFwUpdateInfo->BL1FileName); + + + Print (L"Enter UEFI File Name (%a): ", pFwUpdateInfo->UefiFileName); + + GetHIInputStr(InputFileName, MAX_PATH); + if (StrLen (InputFileName) > 0) + UnicodeStrToAsciiStr(InputFileName, pFwUpdateInfo->UefiFileName); + + + Print (L"Enter TZSW File Name (%a): ", pFwUpdateInfo->TZSWFileName); + + GetHIInputStr(InputFileName, MAX_PATH); + if (StrLen (InputFileName) > 0) + UnicodeStrToAsciiStr(InputFileName, pFwUpdateInfo->TZSWFileName); + } + + Print (L"Select Target Device (1: eMMC, 2: SDCard) (eMMC) :"); + GetHIInputInteger(&TargetMediaId); + + + + if (TargetMediaId > (UINT32)BOOTDEV_MIN && TargetMediaId < (UINT32)BOOTDEV_MAX) + pFwUpdateInfo->TargetMediaID = (FW_BOOT_DEVICE)TargetMediaId; + + + /* Print the final update information on the screen */ + + if (pFwUpdateInfo->SourceType == SOURCE_MEMORY) { + Print(L"BL1:0x%08X, UEFI:0x%08X and TXSW:0x%08X will be updated on %s\n", + pFwUpdateInfo->BL1SourceAddr, + pFwUpdateInfo->UEFISourceAddr, + pFwUpdateInfo->TZSWSourceAddr, + ((pFwUpdateInfo->TargetMediaID == 1)?L"eMMC":L"SD Card")); + + } else { + Print(L"BL1:%a, UEFI:%a and TZSW:%a will be updated on %s\n", + pFwUpdateInfo->BL1FileName, + pFwUpdateInfo->UefiFileName, + pFwUpdateInfo->TZSWFileName, + ((pFwUpdateInfo->TargetMediaID == 1)?L"eMMC":L"SD Card")); + } + + + return EFI_SUCCESS; +} + +VOID SetDefaultFirmwareUpdateInfo( + OUT struct _FW_UPDATE_INFO* pFwUpdateInfo + ) +{ + if (pFwUpdateInfo == NULL) + return; + + pFwUpdateInfo->SourceType = DEFAULT_SOURCE_TYPE; + + pFwUpdateInfo->BL1SourceAddr = DEFAULT_BL1_SOURCE_ADDRESS; + pFwUpdateInfo->UEFISourceAddr = DEFAULT_UEFI_SOURCE_ADDRESS; + pFwUpdateInfo->TZSWSourceAddr = DEFAULT_TZSW_SOURCE_ADDRESS; + + pFwUpdateInfo->TargetMediaID = DEFAULT_TARGET_DEVICE; + + UnicodeStrToAsciiStr(DEFAULT_BL1_SOURCE_FILE, pFwUpdateInfo->BL1FileName); + UnicodeStrToAsciiStr(DEFAULT_UEFI_SOURCE_FILE, pFwUpdateInfo->UefiFileName); + UnicodeStrToAsciiStr(DEFAULT_TZSW_SOURCE_FILE, pFwUpdateInfo->TZSWFileName); + +} + + + +EFI_STATUS +EditHIInputStr ( + IN OUT CHAR16 *CmdLine, + IN UINTN MaxCmdLine + ) +{ + UINTN CmdLineIndex; + UINTN WaitIndex; + CHAR8 Char; + EFI_INPUT_KEY Key; + EFI_STATUS Status; + + Print (CmdLine); + + for (CmdLineIndex = StrLen (CmdLine); CmdLineIndex < MaxCmdLine; ) { + Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex); + ASSERT_EFI_ERROR (Status); + + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + ASSERT_EFI_ERROR (Status); + + // Unicode character is valid when Scancode is NUll + if (Key.ScanCode == SCAN_NULL) { + // Scan code is NUll, hence read Unicode character + Char = (CHAR8)Key.UnicodeChar; + } else { + Char = CHAR_NULL; + } + + if ((Char == CHAR_LINEFEED) || (Char == CHAR_CARRIAGE_RETURN) || (Char == 0x7f)) { + CmdLine[CmdLineIndex] = '\0'; + Print (L"\n\r"); + + return EFI_SUCCESS; + } else if ((Key.UnicodeChar == L'\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){ + if (CmdLineIndex != 0) { + CmdLineIndex--; + Print (L"\b \b"); + } + } else if ((Key.ScanCode == SCAN_ESC) || (Char == 0x1B) || (Char == 0x0)) { + return EFI_INVALID_PARAMETER; + } else { + CmdLine[CmdLineIndex++] = Key.UnicodeChar; + Print (L"%c", Key.UnicodeChar); + } + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +GetHIInputStr ( + IN OUT CHAR16 *CmdLine, + IN UINTN MaxCmdLine + ) +{ + EFI_STATUS Status; + + // For a new input just passed an empty string + CmdLine[0] = L'\0'; + + Status = EditHIInputStr (CmdLine, MaxCmdLine); + + return Status; +} + +EFI_STATUS +GetHIInputInteger ( + OUT UINTN *Integer + ) +{ + CHAR16 CmdLine[255]; + EFI_STATUS Status; + + CmdLine[0] = '\0'; + Status = EditHIInputStr (CmdLine, 255); + if (!EFI_ERROR(Status)) { + *Integer = StrDecimalToUintn (CmdLine); + } + + return Status; +} + +EFI_STATUS +GetHIInputHex ( + OUT UINTN *Integer + ) +{ + CHAR16 CmdLine[255]; + EFI_STATUS Status; + + CmdLine[0] = '\0'; + Status = EditHIInputStr (CmdLine, 255); + if (!EFI_ERROR(Status)) { + *Integer = StrHexToUintn (CmdLine); + } + + return Status; +} diff --git a/SamsungPlatformPkg/Apps/Tools/fwupdate/fwupdate_5250.inf b/SamsungPlatformPkg/Apps/Tools/fwupdate/fwupdate_5250.inf new file mode 100644 index 000000000..eb8fbb158 --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/fwupdate/fwupdate_5250.inf @@ -0,0 +1,54 @@ +## @file +# Sample UEFI Application Reference EDKII Module +# +# This is a sample shell application that will print "UEFI Hello World!" to the +# UEFI Console based on PCD setting. +# +# It demos how to use EDKII PCD mechanism to make code more flexible. +# +# Copyright (c) 2008 - 2011, 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 = fwupdate + FILE_GUID = 6987936E-ED34-44db-AE97-1FA5E4ED2116 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC ARM +# + +[Sources] + fwupdate.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec + SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + PcdLib + EfiFileLib + +[Pcd] + + diff --git a/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl1_5250.bin b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl1_5250.bin Binary files differnew file mode 100644 index 000000000..b7e9b743c --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl1_5250.bin diff --git a/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl1_5250_evt1.bin b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl1_5250_evt1.bin Binary files differnew file mode 100644 index 000000000..ad621e501 --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl1_5250_evt1.bin diff --git a/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl1_5250_evt1_pop.bin b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl1_5250_evt1_pop.bin Binary files differnew file mode 100644 index 000000000..7e0a2c177 --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl1_5250_evt1_pop.bin diff --git a/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl2-5250-ddr3-no-tz.bin b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl2-5250-ddr3-no-tz.bin Binary files differnew file mode 100644 index 000000000..85c9e482c --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl2-5250-ddr3-no-tz.bin diff --git a/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl2-5250-none-evt1-no-tz.bin b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl2-5250-none-evt1-no-tz.bin Binary files differnew file mode 100644 index 000000000..346ac9a6f --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/mkbl2/5250/fwbl2-5250-none-evt1-no-tz.bin diff --git a/SamsungPlatformPkg/Apps/Tools/mkbl2/Makefile b/SamsungPlatformPkg/Apps/Tools/mkbl2/Makefile new file mode 100644 index 000000000..0d52ece52 --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/mkbl2/Makefile @@ -0,0 +1,21 @@ +CC=gcc + +CFLAGS=-g -Wall + +CSRCS = ./mkbl2.c \ + +OBJS = $(CSRCS:.c=.o) + +.SUFFIXES:.c.o + +all: mkbl2 + +testxv: $(OBJS) + $(CC) $(CFLAGS) -g -o $@ $(OBJS) + +.c.o: + $(CC) $(CFLAGS) -g -c -o $@ $< + +clean: + rm -f mkbl2 $(OBJS) + diff --git a/SamsungPlatformPkg/Apps/Tools/mkbl2/imgburn.sh b/SamsungPlatformPkg/Apps/Tools/mkbl2/imgburn.sh new file mode 100755 index 000000000..dee12604a --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/mkbl2/imgburn.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# set the default image filename, this can be overwritten by a parameter +IMAGE=../../../../Build/Arndale-Exynos/DEBUG_ARMLINUXGCC/FV/ARNDALE_EFI.fd + +# set the default SoC, this can be overwritten by a parameter +SOC=5250 + +function usage +{ + echo "Usage: $0" + echo " --disk path to the SD card device to write to, eg /dev/sdd" + echo " This can be found by looking at dmesg output" + echo " --image The image to write to the SD card" + echo " This defaults to:" + echo " $IMAGE" + echo " --soc Which SoC we are using" + echo " This defaults to: 5250" +} + +while [ "$1" != "" ]; do + case $1 in + -s | --soc ) + shift + SOC=$1 + ;; + + -d | --disk ) + shift + DISK=$1 + ;; + + -i | --image ) + shift + IMAGE=$1 + ;; + + /h | /? | -? | -h | --help ) + usage + exit + ;; + -* ) + usage + echo "unknown arg $1" + exit 1 + esac + shift +done + +echo "Config:" +echo "IMAGE $IMAGE" +echo "SoC $SOC" +echo "DISK $DISK" + + +if [ ! -b "$DISK" ] +then + echo "You must specify a valid --disk option" + exit 1 +fi + +if [ ! -f $IMAGE ] +then + echo "" + echo "ERROR: UEFI image $IMAGE does not exist.." + echo "" + exit +fi + +# make mkbl2 +if [ ! -f mkbl2 ] +then + make +fi + +# make BL2 +./mkbl2 $IMAGE + +if [ ! -f fwbl2.bin ] +then + echo "" + echo "ERROR: Failed to create BL2 image." + echo "" + exit +fi + +# select platform +if [ "$SOC" = "5250" ] +then + # write BL1 + dd if=./5250/fwbl1_5250.bin of=$DISK seek=1 count=16 +else + echo "" + echo "ERROR: Please select platform.." + echo "" + exit +fi + + +# write BL2 +dd if=./fwbl2.bin of=$DISK seek=17 count=32 + +# write bootloader file e.g. u-boot or UEFI firmware image +dd if=$IMAGE of=$DISK seek=49 + +sync diff --git a/SamsungPlatformPkg/Apps/Tools/mkbl2/mkbl2.c b/SamsungPlatformPkg/Apps/Tools/mkbl2/mkbl2.c new file mode 100644 index 000000000..55d8b3c7e --- /dev/null +++ b/SamsungPlatformPkg/Apps/Tools/mkbl2/mkbl2.c @@ -0,0 +1,88 @@ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> + + +#define FILE_CHUNK (32*512) + +int main (int argc, char* argv[]) +{ + unsigned char *buffer = NULL; + int src_fd = -1; + int size, offset; + int dest_fd = -1; + unsigned int checksum, addr, i; + + buffer = (unsigned char *)malloc(FILE_CHUNK); + if(NULL == buffer) { + printf("buffer allocation failed\n"); + goto Exit; + } + + src_fd = open(argv[1], O_RDONLY); + if(src_fd == -1) { + printf("source file(%s) open error\n", argv[1]); + goto Exit; + } + + offset = lseek(src_fd, 0, SEEK_END); + if(offset == -1) { + printf("source file seek error SEEK_END\n"); + goto Exit; + } + + printf("source file(%s) size = %d bytes\n", argv[1], offset); + + offset = lseek(src_fd, 0, SEEK_SET); + if(offset == -1) { + printf("source file seek error SEEK_SET\n"); + goto Exit; + } + + size = read(src_fd, (void *)buffer, FILE_CHUNK); + if(size != FILE_CHUNK) { + printf("source file read error, size=%d\n", size); + goto Exit; + } + + addr = (unsigned int)buffer; + + for(i=0, checksum=0;i<((14*1024) -4);i++) + checksum += *((unsigned char *)addr++); + + *((unsigned int *)addr) = checksum; + + dest_fd = open("./fwbl2.bin", (O_CREAT|O_RDWR), (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)); + if(dest_fd == -1) { + printf("target file(fwbl2.bin) open error\n"); + goto Exit; + } + + size = write(dest_fd, (void *)buffer, FILE_CHUNK); + if(size != FILE_CHUNK) { + printf("target file write error, size=%d\n", size); + goto Exit; + } + + offset = lseek(dest_fd, 0, SEEK_END); + if(offset == -1) { + printf("target file seek error SEEK_END\n"); + goto Exit; + } + + printf("target file(./fwbl2.bin) size = %d bytes\n", offset); + +Exit: + if(buffer != NULL) + free(buffer); + + if(src_fd != -1) + close(src_fd); + + if(dest_fd != -1) + close(dest_fd); + + return 0; +} diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dec b/SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dec new file mode 100644 index 000000000..f8313b734 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dec @@ -0,0 +1,43 @@ +#/** @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 = ArndalePkg + PACKAGE_GUID = 4c9e432c-b84e-44fd-a796-f4545deec144 + 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] #bc92b024-79f8-11e0-a039-0026b9733e2c + gArndaleBoardPkgTokenSpaceGuid = { 0xbc92b024, 0x79f8, 0x11e0, { 0xa0, 0x39, 0x00, 0x26, 0xb9, 0x73, 0x3e, 0x2c} } + +[PcdsFeatureFlag.common] + +[PcdsFixedAtBuild.common] + +[Protocols.common] diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dsc.inc b/SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dsc.inc new file mode 100644 index 000000000..671ef131a --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dsc.inc @@ -0,0 +1,316 @@ +# +# 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. +# +# + +[LibraryClasses.common] +!if $(TARGET) == RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf +!else + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf +# UncachedMemoryAllocationLib|ArmPkg/Library/DebugUncachedMemoryAllocationLib/DebugUncachedMemoryAllocationLib.inf +!endif + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + + # + # Assume everything is fixed at build + # + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + + # 1/123 faster than Stm or Vstm version + #BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + BaseMemoryLib|ArmPkg/Library/BaseMemoryLibStm/BaseMemoryLibStm.inf + + # ARM Architectural Libraries + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf + DmaLib|ArmPkg/Library/ArmDmaLib/ArmDmaLib.inf + + # EBL Related Libraries + EblCmdLib|ArmPlatformPkg/Library/EblCmdLib/EblCmdLib.inf + EfiFileLib|EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf + EblAddExternalCommandLib|EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf + EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf + + # + # Uncomment (and comment out the next line) For Samsung Debugger. The Standard IO window + # in the debugger will show load and unload commands for symbols. You can cut and paste this + # into the command window to load symbols. We should be able to use a script to do this, but + # the version of RVD I have does not support scripts accessing system memory. + # + #PeCoffExtraActionLib|ArmPkg/Library/RvdPeCoffExtraActionLib/RvdPeCoffExtraActionLib.inf + PeCoffExtraActionLib|ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.inf + #PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + DebugAgentTimerLib|SamsungPlatformPkg/ArndaleBoardPkg/Library/DebugAgentTimerLib/DebugAgentTimerLib.inf + + SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf + + # BDS Libraries + BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf + +[LibraryClasses.common.SEC] + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf +ArmPlatformSecLib|ArmPlatformPkg/Library/ArmPlatformSecLibNull/ArmPlatformLibNullSec.inf + ArmPlatformSecExtraActionLib|ArmPlatformPkg/Library/DebugSecExtraActionLib/DebugSecExtraActionLib.inf + ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Sec/SecArmPlatformGlobalVariableLib.inf + + DebugAgentLib|ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf + DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLibBase.inf + +#!ifdef $(EDK2_SKIP_PEICORE) + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + LzmaDecompressLib|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + MemoryAllocationLib|EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf + HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf + PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf + PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf + MemoryInitPeiLib|ArmPlatformPkg/MemoryInitPei/MemoryInitPeiLib.inf +#!endif + + # Trustzone Support + ArmTrustedMonitorLib|ArmPlatformPkg/Library/ArmTrustedMonitorLibNull/ArmTrustedMonitorLibNull.inf + +[LibraryClasses.common.PEI_CORE] + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + + ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Pei/PeiArmPlatformGlobalVariableLib.inf + PeiServicesTablePointerLib|ArmPlatformPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + +[LibraryClasses.common.PEIM] + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeiResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + + ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Pei/PeiArmPlatformGlobalVariableLib.inf + PeiServicesTablePointerLib|ArmPlatformPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + +[LibraryClasses.common.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf + +[LibraryClasses.common.DXE_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Dxe/DxeArmPlatformGlobalVariableLib.inf + + GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf + PlatformBdsLib|SamsungPlatformPkg/Library/PlatformBdsLib/PlatformBdsLib.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + + +[LibraryClasses.common.UEFI_APPLICATION] + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + +[LibraryClasses.ARM] + # + # It is not possible to prevent the ARM compiler for generic intrinsic functions. + # This library provides the instrinsic functions generate by a given compiler. + # [LibraryClasses.ARM] and NULL mean link this library into all ARM images. + # + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf + +[BuildOptions] + RVCT:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG + + GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG + + XCODE:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE + + gEmbeddedTokenSpaceGuid.PcdCacheEnable|TRUE + + # Use the Vector Table location in CpuDxe. We will not copy the Vector Table at PcdCpuVectorBaseAddress + gArmTokenSpaceGuid.PcdRelocateVectorTable|FALSE + + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE + + gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE + +[PcdsFixedAtBuild.common] + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0 + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000 + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|1 + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320 + + # DEBUG_ASSERT_ENABLED 0x01 + # DEBUG_PRINT_ENABLED 0x02 + # DEBUG_CODE_ENABLED 0x04 + # CLEAR_MEMORY_ENABLED 0x08 + # ASSERT_BREAKPOINT_ENABLED 0x10 + # ASSERT_DEADLOOP_ENABLED 0x20 +!if $(TARGET) == RELEASE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x21 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f +!endif + + # DEBUG_INIT 0x00000001 // Initialization + # DEBUG_WARN 0x00000002 // Warnings + # DEBUG_LOAD 0x00000004 // Load events + # DEBUG_FS 0x00000008 // EFI File system + # DEBUG_POOL 0x00000010 // Alloc & Free's + # DEBUG_PAGE 0x00000020 // Alloc & Free's + # DEBUG_INFO 0x00000040 // Verbose + # DEBUG_DISPATCH 0x00000080 // PEI/DXE Dispatchers + # DEBUG_VARIABLE 0x00000100 // Variable + # DEBUG_BM 0x00000400 // Boot Manager + # DEBUG_BLKIO 0x00001000 // BlkIo Driver + # DEBUG_NET 0x00004000 // SNI Driver + # DEBUG_UNDI 0x00010000 // UNDI Driver + # DEBUG_LOADFILE 0x00020000 // UNDI Driver + # DEBUG_EVENT 0x00080000 // Event messages + # DEBUG_GCD 0x00100000 // GCD + # DEBUG_ERROR 0x80000000 // Error + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000000F + + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + + gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|"" + #gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|"start fs1\:\\efi\\boot\\bootarm.efi" + gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07 + gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000 + + # + # Optional feature to help prevent EFI memory map fragments + # Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob + # Values are in EFI Pages (4K). DXE Core will make sure that + # at least this much of each type of memory can be allocated + # from a single memory range. This way you only end up with + # maximum of two fragements for each type in the memory map + # (the memory used, and the free memory that was prereserved + # but not used). + # + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0x00000000 + + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|80 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|40 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|400 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|800 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|10 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0 + + + # + # ARM OS Loader + # + gArmTokenSpaceGuid.PcdArmMachineType|2456 + gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription|L"Linaro image on SD card" + gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath|L"VenHw(3A02E7FE-0649-4FB4-BE4F-A862CA1872A9)/HD(2,MBR,0x00000000,0x2000,0x1A000)/uImage" + gArmPlatformTokenSpaceGuid.PcdDefaultBootInitrdPath|L"VenHw(3A02E7FE-0649-4FB4-BE4F-A862CA1872A9)/HD(2,MBR,0x00000000,0x2000,0x1A000)/uInitrd" + gArmPlatformTokenSpaceGuid.PcdDefaultFdtLocalDevicePath|L"VenHw(3A02E7FE-0649-4FB4-BE4F-A862CA1872A9)/HD(2,MBR,0x00000000,0x2000,0x1A000)/board.dtb" + gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|"root=/dev/mmcblk1p3 rw rootwait console=ttySAC2,115200n8 init --no-log" + gArmPlatformTokenSpaceGuid.PcdDefaultBootType|3 + gArmPlatformTokenSpaceGuid.PcdFdtDevicePath|L"VenHw(3A02E7FE-0649-4FB4-BE4F-A862CA1872A9)/HD(2,MBR,0x00000000,0x2000,0x1A000)/board.dtb" + + # Use the Serial console (ConIn & ConOut) and the Graphic driver (ConOut) + gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(115200,8,N,1)/VenPcAnsi();VenHw(9042A9DE-23DC-4A38-96FB-7ADED080516A)" + gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(115200,8,N,1)/VenPcAnsi()" + + gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|10 + + # + # Boot Application + # + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x4A, 0x35, 0xEF, 0x3C, 0x7A, 0x3B, 0x19, 0x45, 0xAD, 0x70, 0x72, 0xA1, 0x34, 0x69, 0x83, 0x11 } diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/EBLoadSecSyms.inc b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/EBLoadSecSyms.inc new file mode 100644 index 000000000..281c99b4a --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/EBLoadSecSyms.inc @@ -0,0 +1,15 @@ +// returns the base address of the SEC FV in flash on the EB board +// change this address for where your platform's SEC FV is located +// (or make it more intelligent to search for it) +define /r FindFv() +{ + return 0x40000000; +} +. + +include /s 'ZZZZZZ/EfiFuncs.inc' +error=continue +unload ,all +error=abort +LoadPeiSec() +include C:\loadfiles.inc diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/EfiFuncs.inc b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/EfiFuncs.inc new file mode 100644 index 000000000..014d09440 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/EfiFuncs.inc @@ -0,0 +1,463 @@ +error=abort + +// NOTE: THIS MAY NEED TO BE ADJUSTED +// change to reflect the total amount of ram in your system +define /r GetMaxMem() +{ + return 0x10000000; // 256 MB +} +. + +define /r GetWord(Addr) +{ + unsigned long data; + + if( (Addr & 0x2) == 0 ) + { + data = dword(Addr); + data = data & 0xffff; + //$printf "getword data is %x\n", data$; + return data; + } + else + { + data = dword(Addr & 0xfffffffc); + //data = data >> 16; + data = data / 0x10000; + //$printf "getword data is %x (1)\n", data$; + return data; + } +} +. + +define /r ProcessPE32(imgstart) +unsigned long imgstart; +{ + unsigned long filehdrstart; + unsigned long debugdirentryrva; + unsigned long debugtype; + unsigned long debugrva; + unsigned long dwarfsig; + unsigned long baseofcode; + unsigned long baseofdata; + unsigned long elfbase; + char *elfpath; + + $printf "PE32 image found at %x",imgstart$; + + //$printf "PE file hdr offset %x",dword(imgstart+0x3C)$; + + // offset from dos hdr to PE file hdr + filehdrstart = imgstart + dword(imgstart+0x3C); + + // offset to debug dir in PE hdrs + //$printf "debug dir is at %x",(filehdrstart+0xA8)$; + debugdirentryrva = dword(filehdrstart + 0xA8); + if(debugdirentryrva == 0) + { + $printf "no debug dir for image at %x",imgstart$; + return; + } + + //$printf "debug dir entry rva is %x",debugdirentryrva$; + + debugtype = dword(imgstart + debugdirentryrva + 0xc); + if( (debugtype != 0xdf) && (debugtype != 0x2) ) + { + $printf "debug type is not dwarf for image at %x",imgstart$; + $printf "debug type is %x",debugtype$; + return; + } + + debugrva = dword(imgstart + debugdirentryrva + 0x14); + dwarfsig = dword(imgstart + debugrva); + if(dwarfsig != 0x66727764) + { + $printf "dwarf debug signature not found for image at %x",imgstart$; + return; + } + + elfpath = (char *)(imgstart + debugrva + 0xc); + + baseofcode = imgstart + dword(filehdrstart + 0x28); + baseofdata = imgstart + dword(filehdrstart + 0x2c); + + if( (baseofcode < baseofdata) && (baseofcode != 0) ) + { + elfbase = baseofcode; + } + else + { + elfbase = baseofdata; + } + + $printf "found path %s",elfpath$; + $fprintf 50, "load /ni /np /a %s &0x%x\n",elfpath,elfbase$; +} +. + +define /r ProcessTE(imgstart) +unsigned long imgstart; +{ + unsigned long strippedsize; + unsigned long debugdirentryrva; + unsigned long debugtype; + unsigned long debugrva; + unsigned long dwarfsig; + unsigned long elfbase; + char *elfpath; + + $printf "TE image found at %x",imgstart$; + + // determine pe header bytes removed to account for in rva references + //strippedsize = word(imgstart + 0x6); + //strippedsize = (dword(imgstart + 0x4) & 0xffff0000) >> 16; + strippedsize = (dword(imgstart + 0x4) & 0xffff0000) / 0x10000; + strippedsize = strippedsize - 0x28; + + debugdirentryrva = dword(imgstart + 0x20); + if(debugdirentryrva == 0) + { + $printf "no debug dir for image at %x",imgstart$; + return; + } + debugdirentryrva = debugdirentryrva - strippedsize; + + //$printf "debug dir entry rva is %x",debugdirentryrva$; + + debugtype = dword(imgstart + debugdirentryrva + 0xc); + if( (debugtype != 0xdf) && (debugtype != 0x2) ) + { + $printf "debug type is not dwarf for image at %x",imgstart$; + $printf "debug type is %x",debugtype$; + return; + } + + debugrva = dword(imgstart + debugdirentryrva + 0x14); + debugrva = debugrva - strippedsize; + dwarfsig = dword(imgstart + debugrva); + if( (dwarfsig != 0x66727764) && (dwarfsig != 0x3031424e) ) + { + $printf "dwarf debug signature not found for image at %x",imgstart$; + $printf "found %x", dwarfsig$; + return; + } + + if( dwarfsig == 0x66727764 ) + { + elfpath = (char *)(imgstart + debugrva + 0xc); + $printf "looking for elf path at 0x%x", elfpath$; + } + else + { + elfpath = (char *)(imgstart + debugrva + 0x10); + $printf "looking for elf path at 0x%x", elfpath$; + } + + // elf base is baseofcode (we hope that for TE images it's not baseofdata) + elfbase = imgstart + dword(imgstart + 0xc) - strippedsize; + + $printf "found path %s",elfpath$; + $fprintf 50, "load /ni /np /a %s &0x%x\n",elfpath,elfbase$; +} +. + +define /r ProcessFvSection(secstart) +unsigned long secstart; +{ + unsigned long sectionsize; + unsigned char sectiontype; + + sectionsize = dword(secstart); + //sectiontype = (sectionsize & 0xff000000) >> 24; + sectiontype = (sectionsize & 0xff000000) / 0x1000000; + sectionsize = sectionsize & 0x00ffffff; + + $printf "fv section at %x size %x type %x",secstart,sectionsize,sectiontype$; + + if(sectiontype == 0x10) // PE32 + { + ProcessPE32(secstart+0x4); + } + else if(sectiontype == 0x12) // TE + { + ProcessTE(secstart+0x4); + } +} +. + +define /r ProcessFfsFile(ffsfilestart) +unsigned long ffsfilestart; +{ + unsigned long ffsfilesize; + unsigned long ffsfiletype; + unsigned long secoffset; + unsigned long secsize; + + //ffsfiletype = byte(ffsfilestart + 0x12); + ffsfilesize = dword(ffsfilestart + 0x14); + //ffsfiletype = (ffsfilesize & 0xff000000) >> 24; + ffsfiletype = (ffsfilesize & 0xff000000) / 0x1000000; + ffsfilesize = ffsfilesize & 0x00ffffff; + + if(ffsfiletype == 0xff) return; + + $printf "ffs file at %x size %x type %x",ffsfilestart,ffsfilesize,ffsfiletype$; + + secoffset = ffsfilestart + 0x18; + + // loop through sections in file + while(secoffset < (ffsfilestart + ffsfilesize)) + { + // process fv section and increment section offset by size + secsize = dword(secoffset) & 0x00ffffff; + ProcessFvSection(secoffset); + secoffset = secoffset + secsize; + + // align to next 4 byte boundary + if( (secoffset & 0x3) != 0 ) + { + secoffset = secoffset + (0x4 - (secoffset & 0x3)); + } + } // end section loop +} +. + +define /r LoadPeiSec() +{ + unsigned long fvbase; + unsigned long fvlen; + unsigned long fvsig; + unsigned long ffsoffset; + unsigned long ffsfilesize; + + fvbase = FindFv(); + $printf "fvbase %x",fvbase$; + + // get fv signature field + fvsig = dword(fvbase + 0x28); + if(fvsig != 0x4856465F) + { + $printf "FV does not have proper signature, exiting"$; + return 0; + } + + $printf "FV signature found"$; + + $fopen 50, 'C:\loadfiles.inc'$; + + fvlen = dword(fvbase + 0x20); + + // first ffs file is after fv header, use headerlength field + //ffsoffset = (dword(fvbase + 0x30) & 0xffff0000) >> 16; + ffsoffset = (dword(fvbase + 0x30) & 0xffff0000) / 0x10000; + ffsoffset = fvbase + GetWord(fvbase + 0x30); + + // loop through ffs files + while(ffsoffset < (fvbase+fvlen)) + { + // process ffs file and increment by ffs file size field + ProcessFfsFile(ffsoffset); + ffsfilesize = (dword(ffsoffset + 0x14) & 0x00ffffff); + if(ffsfilesize == 0) + { + break; + } + ffsoffset = ffsoffset + ffsfilesize; + + + // align to next 8 byte boundary + if( (ffsoffset & 0x7) != 0 ) + { + ffsoffset = ffsoffset + (0x8 - (ffsoffset & 0x7)); + } + + } // end fv ffs loop + + $vclose 50$; + +} +. + +define /r FindSystemTable(TopOfRam) +unsigned long TopOfRam; +{ + unsigned long offset; + + $printf "FindSystemTable"$; + $printf "top of mem is %x",TopOfRam$; + + offset = TopOfRam; + + // align to highest 4MB boundary + offset = offset & 0xFFC00000; + + // start at top and look on 4MB boundaries for system table ptr structure + while(offset > 0) + { + //$printf "checking %x",offset$; + //$printf "value is %x",dword(offset)$; + + // low signature match + if(dword(offset) == 0x20494249) + { + // high signature match + if(dword(offset+4) == 0x54535953) + { + // less than 4GB? + if(dword(offset+0x0c) == 0) + { + // less than top of ram? + if(dword(offset+8) < TopOfRam) + { + return(dword(offset+8)); + } + } + } + + } + + if(offset < 0x400000) break; + offset = offset - 0x400000; + } + + return 0; +} +. + +define /r ProcessImage(ImageBase) +unsigned long ImageBase; +{ + $printf "ProcessImage %x", ImageBase$; +} +. + +define /r FindDebugInfo(SystemTable) +unsigned long SystemTable; +{ + unsigned long CfgTableEntries; + unsigned long ConfigTable; + unsigned long i; + unsigned long offset; + unsigned long dbghdr; + unsigned long dbgentries; + unsigned long dbgptr; + unsigned long dbginfo; + unsigned long loadedimg; + + $printf "FindDebugInfo"$; + + dbgentries = 0; + CfgTableEntries = dword(SystemTable + 0x40); + ConfigTable = dword(SystemTable + 0x44); + + $printf "config table is at %x (%d entries)", ConfigTable, CfgTableEntries$; + + // now search for debug info entry with guid 49152E77-1ADA-4764-B7A2-7AFEFED95E8B + // 0x49152E77 0x47641ADA 0xFE7AA2B7 0x8B5ED9FE + for(i=0; i<CfgTableEntries; i++) + { + offset = ConfigTable + (i*0x14); + if(dword(offset) == 0x49152E77) + { + if(dword(offset+4) == 0x47641ADA) + { + if(dword(offset+8) == 0xFE7AA2B7) + { + if(dword(offset+0xc) == 0x8B5ED9FE) + { + dbghdr = dword(offset+0x10); + dbgentries = dword(dbghdr + 4); + dbgptr = dword(dbghdr + 8); + } + } + } + } + } + + if(dbgentries == 0) + { + $printf "no debug entries found"$; + return; + } + + $printf "debug table at %x (%d entries)", dbgptr, dbgentries$; + + for(i=0; i<dbgentries; i++) + { + dbginfo = dword(dbgptr + (i*4)); + if(dbginfo != 0) + { + if(dword(dbginfo) == 1) // normal debug info type + { + loadedimg = dword(dbginfo + 4); + ProcessPE32(dword(loadedimg + 0x20)); + } + } + } +} +. + +define /r LoadDxe() +{ + unsigned long maxmem; + unsigned long systbl; + + $printf "LoadDxe"$; + + $fopen 50, 'C:\loadfiles.inc'$; + + maxmem = GetMaxMem(); + systbl = FindSystemTable(maxmem); + if(systbl != 0) + { + $printf "found system table at %x",systbl$; + FindDebugInfo(systbl); + } + + $vclose 50$; +} +. + +define /r LoadRuntimeDxe() + +{ + unsigned long maxmem; + unsigned long SystemTable; + unsigned long CfgTableEntries; + unsigned long ConfigTable; + unsigned long i; + unsigned long offset; + unsigned long numentries; + unsigned long RuntimeDebugInfo; + unsigned long DebugInfoOffset; + unsigned long imgbase; + + $printf "LoadRuntimeDxe"$; + + $fopen 50, 'C:\loadfiles.inc'$; + + RuntimeDebugInfo = 0x80000010; + + if(RuntimeDebugInfo != 0) + { + numentries = dword(RuntimeDebugInfo); + + $printf "runtime debug info is at %x (%d entries)", RuntimeDebugInfo, numentries$; + + DebugInfoOffset = RuntimeDebugInfo + 0x4; + for(i=0; i<numentries; i++) + { + imgbase = dword(DebugInfoOffset); + if(imgbase != 0) + { + $printf "found image at %x",imgbase$; + ProcessPE32(imgbase); + } + DebugInfoOffset = DebugInfoOffset + 0x4; + } + } + + $vclose 50$; +} +. diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc new file mode 100644 index 000000000..cd273a423 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc @@ -0,0 +1,20 @@ +// +// 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. +// +error = continue +unload +error = abort + +setreg @CP15_CONTROL = 0x0005107E +setreg @pc=0x80008208 +setreg @cpsr=0x000000D3 +dis/D +readfile,raw,nowarn "ZZZZZZ/FV/BEAGLEBOARD_EFI.fd"=0x80008000 diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh new file mode 100644 index 000000000..46dd65cf3 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# 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. +# + + +IN=`/usr/bin/cygpath -u $1` +OUT=`/usr/bin/cygpath -u $2` + +/usr/bin/sed -e "s/\/cygdrive\/\(.\)/load\/a\/ni\/np \"\1:/g" \ + -e 's:\\:/:g' \ + -e "s/^/load\/a\/ni\/np \"/g" \ + -e "s/dll /dll\" \&/g" \ + $IN | /usr/bin/sort.exe --key=3 --output=$OUT diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_hw_setup.inc b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_hw_setup.inc new file mode 100644 index 000000000..c03a443e8 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_hw_setup.inc @@ -0,0 +1,67 @@ +// +// 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. +// + +error = continue +unload +error = abort + +setreg @CP15_CONTROL = 0x0005107E +setreg @cpsr=0x000000D3 + +; General clock settings. +setmem /32 0x48307270=0x00000080 +setmem /32 0x48306D40=0x00000003 +setmem /32 0x48005140=0x03020A50 + +;Clock configuration +setmem /32 0x48004A40=0x0000030A +setmem /32 0x48004C40=0x00000015 + +;DPLL3 (Core) settings +setmem /32 0x48004D00=0x00370037 +setmem /32 0x48004D30=0x00000000 +setmem /32 0x48004D40=0x094C0C00 + +;DPLL4 (Peripheral) settings +setmem /32 0x48004D00=0x00370037 +setmem /32 0x48004D30=0x00000000 +setmem /32 0x48004D44=0x0001B00C +setmem /32 0x48004D48=0x00000009 + +;DPLL1 (MPU) settings +setmem /32 0x48004904=0x00000037 +setmem /32 0x48004934=0x00000000 +setmem /32 0x48004940=0x0011F40C +setmem /32 0x48004944=0x00000001 +setmem /32 0x48004948=0x00000000 + +;RAM setup. +setmem /16 0x6D000010=0x0000 +setmem /16 0x6D000040=0x0001 +setmem /16 0x6D000044=0x0100 +setmem /16 0x6D000048=0x0000 +setmem /32 0x6D000060=0x0000000A +setmem /32 0x6D000070=0x00000081 +setmem /16 0x6D000040=0x0003 +setmem /32 0x6D000080=0x02D04011 +setmem /16 0x6D000084=0x0032 +setmem /16 0x6D00008C=0x0000 +setmem /32 0x6D00009C=0xBA9DC4C6 +setmem /32 0x6D0000A0=0x00012522 +setmem /32 0x6D0000A4=0x0004E201 +setmem /16 0x6D000040=0x0003 +setmem /32 0x6D0000B0=0x02D04011 +setmem /16 0x6D0000B4=0x0032 +setmem /16 0x6D0000BC=0x0000 +setmem /32 0x6D0000C4=0xBA9DC4C6 +setmem /32 0x6D0000C8=0x00012522 +setmem /32 0x6D0000D4=0x0004E201
\ No newline at end of file diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_load_symbols.inc b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_load_symbols.inc new file mode 100644 index 000000000..a8f98433d --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_load_symbols.inc @@ -0,0 +1,21 @@ +// +// 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 'ZZZZZZ/rvi_symbols_macros.inc' + +macro write_symbols_file("ZZZZZZ/rvi_symbols.tmp", 0x00000000, 0x10000000) + +host "bash -o igncr ZZZZZZ/rvi_convert_symbols.sh ZZZZZZ/rvi_symbols.tmp ZZZZZZ/rvi_symbols.inc" +include 'ZZZZZZ/rvi_symbols.inc' +load /NI /NP 'ZZZZZZ/rvi_dummy.axf' ;.constdata +unload rvi_dummy.axf +delfile rvi_dummy.axf diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc new file mode 100644 index 000000000..6f7377cbb --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc @@ -0,0 +1,193 @@ +// +// 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. +// + +define /R int compare_guid(guid1, guid2) + unsigned char *guid1; + unsigned char *guid2; +{ + return strncmp(guid1, guid2, 16); +} +. + +define /R unsigned char * find_system_table(mem_start, mem_size) + unsigned char *mem_start; + unsigned long mem_size; +{ + unsigned char *mem_ptr; + + mem_ptr = mem_start + mem_size; + + do + { + mem_ptr -= 0x400000; // 4 MB + + if (strncmp(mem_ptr, "IBI SYST", 8) == 0) + { + return *(unsigned long *)(mem_ptr + 8); // EfiSystemTableBase + } + + } while (mem_ptr > mem_start); + + return 0; +} +. + +define /R unsigned char * find_debug_info_table_header(system_table) + unsigned char *system_table; +{ + unsigned long configuration_table_entries; + unsigned char *configuration_table; + unsigned long index; + unsigned char debug_table_guid[16]; + + // Fill in the debug table's guid + debug_table_guid[ 0] = 0x77; + debug_table_guid[ 1] = 0x2E; + debug_table_guid[ 2] = 0x15; + debug_table_guid[ 3] = 0x49; + debug_table_guid[ 4] = 0xDA; + debug_table_guid[ 5] = 0x1A; + debug_table_guid[ 6] = 0x64; + debug_table_guid[ 7] = 0x47; + debug_table_guid[ 8] = 0xB7; + debug_table_guid[ 9] = 0xA2; + debug_table_guid[10] = 0x7A; + debug_table_guid[11] = 0xFE; + debug_table_guid[12] = 0xFE; + debug_table_guid[13] = 0xD9; + debug_table_guid[14] = 0x5E; + debug_table_guid[15] = 0x8B; + + configuration_table_entries = *(unsigned long *)(system_table + 64); + configuration_table = *(unsigned long *)(system_table + 68); + + for (index = 0; index < configuration_table_entries; index++) + { + if (compare_guid(configuration_table, debug_table_guid) == 0) + { + return *(unsigned long *)(configuration_table + 16); + } + + configuration_table += 20; + } + + return 0; +} +. + +define /R int valid_pe_header(header) + unsigned char *header; +{ + if ((header[0x00] == 'M') && + (header[0x01] == 'Z') && + (header[0x80] == 'P') && + (header[0x81] == 'E')) + { + return 1; + } + + return 0; +} +. + +define /R unsigned long pe_headersize(header) + unsigned char *header; +{ + unsigned long *size; + + size = header + 0x00AC; + + return *size; +} +. + +define /R unsigned char *pe_filename(header) + unsigned char *header; +{ + unsigned long *debugOffset; + unsigned char *stringOffset; + + if (valid_pe_header(header)) + { + debugOffset = header + 0x0128; + stringOffset = header + *debugOffset + 0x002C; + + return stringOffset; + } + + return 0; +} +. + +define /R int char_is_valid(c) + unsigned char c; +{ + if (c >= 32 && c < 127) + return 1; + + return 0; +} +. + +define /R write_symbols_file(filename, mem_start, mem_size) + unsigned char *filename; + unsigned char *mem_start; + unsigned long mem_size; +{ + unsigned char *system_table; + unsigned char *debug_info_table_header; + unsigned char *debug_info_table; + unsigned long debug_info_table_size; + unsigned long index; + unsigned char *debug_image_info; + unsigned char *loaded_image_protocol; + unsigned char *image_base; + unsigned char *debug_filename; + unsigned long header_size; + int status; + + system_table = find_system_table(mem_start, mem_size); + if (system_table == 0) + { + return; + } + + status = fopen(88, filename, "w"); + + debug_info_table_header = find_debug_info_table_header(system_table); + + debug_info_table = *(unsigned long *)(debug_info_table_header + 8); + debug_info_table_size = *(unsigned long *)(debug_info_table_header + 4); + + for (index = 0; index < (debug_info_table_size * 4); index += 4) + { + debug_image_info = *(unsigned long *)(debug_info_table + index); + + if (debug_image_info == 0) + { + break; + } + + loaded_image_protocol = *(unsigned long *)(debug_image_info + 4); + + image_base = *(unsigned long *)(loaded_image_protocol + 32); + + debug_filename = pe_filename(image_base); + header_size = pe_headersize(image_base); + + $fprintf 88, "%s 0x%08x\n", debug_filename, image_base + header_size$; + } + + + fclose(88); +} +. diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc new file mode 100644 index 000000000..4a7e12b81 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc @@ -0,0 +1,118 @@ +// +// 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. +// + +error = continue + +unload + +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 +delfile 1 + +error = abort diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/FvbDxe/FvbDxe.c b/SamsungPlatformPkg/ArndaleBoardPkg/FvbDxe/FvbDxe.c new file mode 100755 index 000000000..18d13d570 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/FvbDxe/FvbDxe.c @@ -0,0 +1,621 @@ +/*++ + FVB DXE Driver + +Copyright (c) 2012, Samsung 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/BaseMemoryLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/PcdLib.h> +#include <Protocol/FirmwareVolumeBlock.h> +#include <Protocol/BlockIo.h> +#include <Library/MemoryAllocationLib.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); +EFI_BLOCK_IO_PROTOCOL *BlockIo; +EFI_EVENT mBlockIORegistration = NULL; +EFI_HANDLE mHandle = NULL; +UINT32 TargetMediaId; + +#define EMMC_BLOCK_SIZE 512 +#define EMMC_BLOCK_NUMBER 512 +#define MSHC_BOOT_NV_OFFSET 0x1000 +#define NV_READ_BUFFER_SIZE 0x20000 +#define FVB_HEADER_LEN 0x64 +#define DMA_BUFFER_NV_OFFSET 0x60000 + +VOID *BufPtr; +VOID *ReadBufPtr; + +#define FVB_TEST 0 +//VOID *TestBufPtr; + +/** + 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, "FVB: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, "FVB: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 + ) +{ + EFI_PHYSICAL_ADDRESS NVBase = PcdGet32(PcdFlashNvStorageVariableBase); + //UINT32 NVSize = PcdGet32(PcdFlashNvStorageVariableSize); + + *Address = NVBase; + //DEBUG ((EFI_D_INFO, "FVB: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 = EMMC_BLOCK_SIZE; + *NumberOfBlocks = EMMC_BLOCK_NUMBER; + DEBUG ((EFI_D_INFO, "FVB: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. + +**/ +UINT8 FVB_Header[100]={0xff,}; + +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_STATUS Status = EFI_SUCCESS; + UINT32 NumBlock; + UINT32 AllocSize = 0; + EFI_LBA NV_Lba = Lba + MSHC_BOOT_NV_OFFSET; + UINT32 NVBase = PcdGet32(PcdFlashNvStorageVariableBase); + + DEBUG ((EFI_D_INFO, "FVB:FvbRead O:%d ",Offset)); + DEBUG ((EFI_D_INFO, "Lba:%d \n",Lba)); + DEBUG ((EFI_D_INFO, "N:%d \n",*NumBytes)); + + // check invalid input parameter + if(*NumBytes<=0){ + goto Exit; + } + if((*NumBytes-1)>=(MAX_ADDRESS-(UINTN)Buffer)){ + goto Exit; + } + + // 1. Copy FVB header + CopyMem(&FVB_Header[0], (UINT8 *)NVBase, 100); + + // 2. calculate block number and allocate memory + // 3. ReadBlock + if (0 == ((Offset + *NumBytes)%EMMC_BLOCK_SIZE)) + { + NumBlock = ((Offset + *NumBytes)/EMMC_BLOCK_SIZE); + } + else + { + NumBlock = ((Offset + *NumBytes)/EMMC_BLOCK_SIZE)+1; + } + AllocSize = NumBlock*EMMC_BLOCK_SIZE; + Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, NV_Lba, AllocSize, (UINT8 *)NVBase); + + if (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NVBase))->Signature != EFI_FVH_SIGNATURE) + { + DEBUG ((EFI_D_ERROR, "FVB:FvbRead invalid header\n")); + CopyMem((UINT8 *)NVBase, &FVB_Header[0], 100); + goto Exit; + } + // 4. Copy read buffer to dest + CopyMem(Buffer, (UINT8 *)(NVBase +Offset), *NumBytes); + + if(Status!=EFI_SUCCESS) + { + DEBUG ((EFI_D_ERROR, "FVB:FvbRead Failed %r\n", Status)); + Status = EFI_ACCESS_DENIED; + } + +Exit: + 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_STATUS Status = EFI_SUCCESS; + UINT32 NumBlock; + UINT32 AllocSize = 0; + EFI_LBA NV_Lba = Lba + MSHC_BOOT_NV_OFFSET; + UINT32 NVBase = PcdGet32(PcdFlashNvStorageVariableBase); + + DEBUG ((EFI_D_INFO, "FvbWrite O:%d\n ", Offset)); + DEBUG ((EFI_D_INFO, "FVB:FvbWrite O:%d ", Offset)); + DEBUG ((EFI_D_INFO, "N:%d ", *NumBytes)); + + // 1. Calculate block count number + if (0 == ((Offset+*NumBytes)%EMMC_BLOCK_SIZE)) + { + NumBlock = ((Offset+*NumBytes)/EMMC_BLOCK_SIZE); + } + else + { + NumBlock = ((Offset+*NumBytes)/EMMC_BLOCK_SIZE) + 1; + } + AllocSize = (NumBlock * EMMC_BLOCK_SIZE); + + CopyMem((UINT8 *)(NVBase + Offset), Buffer, *NumBytes); + + // 4. Apply the offset and WriteBlock + Status = BlockIo->WriteBlocks(BlockIo, TargetMediaId, NV_Lba, AllocSize, (VOID *)(NVBase)); + if(Status!=EFI_SUCCESS) + { + DEBUG ((EFI_D_ERROR, "FVB:FvbWrite Failed %r\n", Status)); + Status = EFI_ACCESS_DENIED; + } + + 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, + ... + ) +{ + DEBUG ((EFI_D_INFO, "FvbEraseBlocks\n")); + return EFI_SUCCESS; +} + + +// +// 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 +}; + + + +/** + Initialize the FVB to use block IO + + + @retval EFI_SUCCESS Protocol registered + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +VOID +EFIAPI +BlockIONotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_HANDLE *HandleBuffer = NULL; + EFI_STATUS Status; + UINTN NumHandles; + UINT32 i; + DEBUG((EFI_D_INFO, "FVB:BlockIONotificationEvent Start \n")); + + TargetMediaId = SIGNATURE_32('e','m','m','c'); + //TargetMediaId ++; + DEBUG((EFI_D_INFO, "FVB:Target Device ID = 0x%x\n", TargetMediaId)); + + if(mHandle!=NULL) + return; + + Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &NumHandles, &HandleBuffer); + + for(i=0;i<NumHandles;i++) { + Status = gBS->HandleProtocol(HandleBuffer[i], &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo); + + DEBUG((EFI_D_INFO, "FVB:Device %d Media ID=0x%x\n", i, BlockIo->Media->MediaId)); + + if((BlockIo->Media->MediaId == TargetMediaId)||(BlockIo->Media->MediaId == (TargetMediaId+1))) + { + DEBUG((EFI_D_INFO, "FVB:InstallFVBProtocol 0x%x \n", BlockIo)); + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, &gFvbProtocol, + NULL + ); + + if(Status!=EFI_SUCCESS) + { + DEBUG((EFI_D_ERROR, "FVB:BlockIO handle is not valid %r\n", Status)); + } + + break; + } + + if(i == NumHandles) { + DEBUG((EFI_D_ERROR, "Cannot find Block IO protocol handle! \n")); + } + } + +} + + + +/** + 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 ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status=EFI_SUCCESS; + + // + // Register FvbNotificationEvent () notify function. + // + + BlockIo = AllocatePool(sizeof(EFI_BLOCK_IO_PROTOCOL)+sizeof(EFI_BLOCK_IO_MEDIA)); + BufPtr = AllocatePool(EMMC_BLOCK_SIZE*2); + if(BufPtr==NULL) + { + DEBUG ((EFI_D_ERROR, "FVB:Temp buffer allocate failed!!!\n")); + } + ReadBufPtr = AllocatePool(NV_READ_BUFFER_SIZE); + if(ReadBufPtr==NULL) + { + DEBUG ((EFI_D_ERROR, "FVB:NV Read buffer allocate failed!!!\n")); + } +#if FVB_TEST + TestBufPtr = AllocatePool(EMMC_BLOCK_SIZE*2); + DEBUG ((EFI_D_ERROR, "FVB:TestBufPtr:0x%x ", TestBufPtr)); +#endif + DEBUG ((EFI_D_ERROR, "BufPtr:0x%x\n", BufPtr)); + + EfiCreateProtocolNotifyEvent ( + &gEfiBlockIoProtocolGuid, + TPL_CALLBACK, + BlockIONotificationEvent, + (VOID *)SystemTable, + &mBlockIORegistration + ); + + DEBUG ((EFI_D_INFO, "\nFVB:FvbDxeInitialize\n")); + + // SetVertAddressEvent () + + // GCD Map NAND as RT + + return Status; +} + diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/FvbDxe/FvbDxe.inf b/SamsungPlatformPkg/ArndaleBoardPkg/FvbDxe/FvbDxe.inf new file mode 100755 index 000000000..450df3caf --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/FvbDxe/FvbDxe.inf @@ -0,0 +1,57 @@ +#/** @file +# +# Copyright (c) 2008 - 2010, 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 = FvbDxe + FILE_GUID = 43ECE281-D9E2-4DD0-B304-E6A5689256F4 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = FvbDxeInitialize + + +[Sources.common] + FvbDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dec + SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec + + +[LibraryClasses] + BaseLib + UefiLib + UefiBootServicesTableLib + DebugLib + PrintLib + UefiDriverEntryPoint + +[Guids] + + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiDiskIoProtocolGuid + gEfiFirmwareVolumeBlockProtocolGuid + +[FixedPcd.common] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferBase + +[depex] + TRUE diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/Board.c b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/Board.c new file mode 100644 index 000000000..364101071 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/Board.c @@ -0,0 +1,226 @@ +/** @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. +* +**/ + +#include <Library/IoLib.h> +#include <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> + +#include <Ppi/ArmMpCoreInfo.h> +#include <Drivers/PL341Dmc.h> +#include <Platform/ArmPlatform.h> + +/** + Return if Trustzone is supported by your platform + + A non-zero value must be returned if you want to support a Secure World on your platform. + ArmPlatformSecTrustzoneInit() will later set up the secure regions. + This function can return 0 even if Trustzone is supported by your processor. In this case, + the platform will continue to run in Secure World. + + @return A non-zero value if Trustzone supported. + +**/ +UINTN ArmPlatformTrustzoneSupported(VOID) { + // There is no Trustzone controllers (TZPC & TZASC) and no Secure Memory on RTSM + return TRUE; +} + +/** + Initialize the Secure peripherals and memory regions + + If Trustzone is supported by your platform then this function makes the required initialization + of the secure peripherals and memory regions. + +**/ +VOID ArmPlatformSecTrustzoneInit( + IN UINTN MpId +) +{ + UINT32 TZPCBase; + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC0_OFFSET; + MmioWrite32((TZPCBase + 0x00),0x00); + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC1_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC2_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC3_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC4_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC5_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC6_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC7_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC8_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT2SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT3SET_OFFSET),0xFF); + + TZPCBase = PcdGet32(PcdTZPCBase) + TZPC9_OFFSET; + MmioWrite32((TZPCBase +TZPC_DECPROT0SET_OFFSET),0xFF); + MmioWrite32((TZPCBase +TZPC_DECPROT1SET_OFFSET),0xFF); + +} + +/** + Remap the memory at 0x0 + + Some platform requires or gives the ability to remap the memory at the address 0x0. + This function can do nothing if this feature is not relevant to your platform. + +**/ +VOID ArmPlatformBootRemapping(VOID) { + // Disable memory remapping and return to normal mapping + MmioOr32 (ARM_EB_SYSCTRL, BIT8); //EB_SP810_CTRL_BASE +} + + +/** + Return the current Boot Mode + + This function returns the boot reason on the platform + + @return Return the current Boot Mode of the platform + +**/ +EFI_BOOT_MODE +ArmPlatformGetBootMode ( + VOID + ) +{ + return BOOT_WITH_FULL_CONFIGURATION; +} + +/** + Initialize controllers that must setup in the normal world + + This function is called by the ArmPlatformPkg/Pei or ArmPlatformPkg/Pei/PlatformPeim + in the PEI phase. + +**/ +VOID +ArmPlatformNormalInitialize ( + VOID + ) +{ + // Nothing to do here +} + +/** + Initialize controllers that must setup in the normal world + + This function is called by the ArmPlatformPkg/PrePi or ArmPlatformPkg/PlatformPei + in the PEI phase. + + **/ +RETURN_STATUS +ArmPlatformInitialize ( + IN UINTN MpId + ) +{ + return RETURN_SUCCESS; +} + + +/** + Initialize the system (or sometimes called permanent) memory + + This memory is generally represented by the DRAM. + +**/ +VOID ArmPlatformInitializeSystemMemory(VOID) { + // We do not need to initialize the System Memory on RTSM +} + +EFI_STATUS +PrePeiCoreGetMpCoreInfo ( + OUT UINTN *CoreCount, + OUT ARM_CORE_INFO **ArmCoreTable + ) +{ +#if 0 + UINT32 ProcType; + + ProcType = MmioRead32 (ARM_VE_SYS_PROCID0_REG) & ARM_VE_SYS_PROC_ID_MASK; + if ((ProcType == ARM_VE_SYS_PROC_ID_CORTEX_A9) || (ProcType == ARM_VE_SYS_PROC_ID_CORTEX_A15)) { + // Only support one cluster + *CoreCount = ArmGetCpuCountPerCluster (); + *ArmCoreTable = mVersatileExpressMpCoreInfoTable; + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } +#endif + return EFI_UNSUPPORTED; +} + +// Needs to be declared in the file. Otherwise gArmMpCoreInfoPpiGuid is undefined in the contect of PrePeiCore +EFI_GUID mArmMpCoreInfoPpiGuid = ARM_MP_CORE_INFO_PPI_GUID; +ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { PrePeiCoreGetMpCoreInfo }; + +EFI_PEI_PPI_DESCRIPTOR gPlatformPpiTable[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &mArmMpCoreInfoPpiGuid, + &mMpCoreInfoPpi + } +}; + +VOID +ArmPlatformGetPlatformPpiList ( + OUT UINTN *PpiListSize, + OUT EFI_PEI_PPI_DESCRIPTOR **PpiList + ) +{ + *PpiListSize = sizeof(gPlatformPpiTable); + *PpiList = gPlatformPpiTable; +} diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.S b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.S new file mode 100755 index 000000000..e47146e47 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.S @@ -0,0 +1,468 @@ +/* + * (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. + * + */ + +#include <Platform/ArmPlatform.h> +#include <Platform/Arndale5250.h> +#include <Platform/Exynos5250_Evt1.h> +#include <Platform/Arndale5250_Val.h> +#include <AutoGen.h> + +GCC_ASM_EXPORT(ArmPlatformClockInitialize) +GCC_ASM_EXPORT(ArmPlatformTZPCInitialize) +GCC_ASM_EXPORT(ArmPlatformSecBootAction) + +wait_pll_lock: + ldr r1, [r0, r2] + tst r1, #(1<<29) + beq wait_pll_lock + mov pc, lr + +wait_mux_state: + add r2, r2, #0x200 + +check_mux_state: + ldr r1, [r0, r2] + orr r4, r1, r3 + cmp r1, r4 + bne check_mux_state + mov pc, lr + +wait_div_state: + add r2, r2, #0x100 + +check_div_state: + ldr r1, [r0, r2] + cmp r1, r3 + bne check_div_state + mov pc, lr + +ASM_PFX(ArmPlatformClockInitialize): + + @push {lr} + mov r12, lr + + ldr r0, =Exynos5250_CMU_BASE @0x1001_0000 + +@ CMU_CPU MUX / DIV + ldr r2, =CLK_SRC_CPU_OFFSET + ldr r3, =0x00000001 + ldr r1, [r0, r2] + bic r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x00000001 + bl wait_mux_state + + ldr r2, =CLK_SRC_CORE1_OFFSET + ldr r3, =0x100 + ldr r1, [r0, r2] + bic r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x00000100 + bl wait_mux_state + + ldr r2, =CLK_SRC_TOP2_OFFSET + ldr r3, =0x10011100 + ldr r1, [r0, r2] + bic r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x10011100 + bl wait_mux_state + + ldr r2, =CLK_SRC_CDREX_OFFSET + ldr r3, =0x1 + ldr r1, [r0, r2] + bic r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x00000001 + bl wait_mux_state + +@ Set PLL locktime + ldr r1, =APLL_LOCK_VAL + ldr r2, =APLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =MPLL_LOCK_VAL + ldr r2, =MPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =BPLL_LOCK_VAL + ldr r2, =BPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =CPLL_LOCK_VAL + ldr r2, =CPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =GPLL_LOCK_VAL + ldr r2, =GPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =EPLL_LOCK_VAL + ldr r2, =EPLL_LOCK_OFFSET + str r1, [r0, r2] + + ldr r1, =VPLL_LOCK_VAL + ldr r2, =VPLL_LOCK_OFFSET + str r1, [r0, r2] + +@ Set BPLL, MPLL Fixed Divider 2 + ldr r1, =0x00 + ldr r2, =PLL_DIV2_SEL_OFFSET + str r1, [r0, r2] + +@ ARM_CLK + ldr r2, =CLK_SRC_CPU_OFFSET + ldr r3, =0x00100000 + str r3, [r0, r2] + ldr r3, =0x00200000 + bl wait_mux_state + + ldr r1, =CLK_DIV_CPU0_VAL @0x01147720 + ldr r2, =CLK_DIV_CPU0_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_CPU1_VAL @0x20 + ldr r2, =CLK_DIV_CPU1_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ Set APLL + ldr r1, =APLL_CON1_VAL + ldr r2, =APLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =APLL_CON0_VAL + ldr r2, =APLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set MPLL @800Mhz + ldr r1, =MPLL_CON1_VAL + ldr r2, =MPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =MPLL_CON0_VAL + ldr r2, =MPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set BPLL @800Mhz + ldr r1, =BPLL_CON1_VAL + ldr r2, =BPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =BPLL_CON0_VAL + ldr r2, =BPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set CPLL @333Mhz + ldr r1, =CPLL_CON1_VAL + ldr r2, =CPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =CPLL_CON0_VAL + ldr r2, =CPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set GPLL @533Mhz + ldr r1, =GPLL_CON1_VAL + ldr r2, =GPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =GPLL_CON0_VAL + ldr r2, =GPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set EPLL @96Mhz + ldr r1, =EPLL_CON2_VAL + ldr r2, =EPLL_CON2_OFFSET + str r1, [r0, r2] + ldr r1, =EPLL_CON1_VAL + ldr r2, =EPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =EPLL_CON0_VAL + ldr r2, =EPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ Set VPLL @300Mhz + ldr r1, =VPLL_CON2_VAL + ldr r2, =VPLL_CON2_OFFSET + str r1, [r0, r2] + ldr r1, =VPLL_CON1_VAL + ldr r2, =VPLL_CON1_OFFSET + str r1, [r0, r2] + ldr r1, =VPLL_CON0_VAL + ldr r2, =VPLL_CON0_OFFSET + str r1, [r0, r2] + bl wait_pll_lock + +@ CMU_CORE MUX / DIV + ldr r2, =CLK_SRC_CORE0_OFFSET + ldr r3, =CLK_SRC_CORE0_VAL + str r3, [r0, r2] + + ldr r1, =CLK_DIV_CORE0_VAL + ldr r2, =CLK_DIV_CORE0_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_CORE1_VAL + ldr r2, =CLK_DIV_CORE1_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_SYSRGT_VAL + ldr r2, =CLK_DIV_SYSRGT_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_ACP DIV + ldr r1, =CLK_DIV_ACP_VAL + ldr r2, =CLK_DIV_ACP_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_SYSLFT_VAL + ldr r2, =CLK_DIV_SYSLFT_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + ldr r2, =CLK_DIV_STAT_SYSLFT_OFFSET +check_div_syslft_state: + ldr r1, [r0, r2] + cmp r1, r3 + bne check_div_syslft_state + +@ CMU_TOP SRC + ldr r2, =CLK_SRC_TOP0_OFFSET + ldr r3, =CLK_SRC_TOP0_VAL + str r3, [r0, r2] + + ldr r2, =CLK_SRC_TOP1_OFFSET + ldr r3, =CLK_SRC_TOP1_VAL + str r3, [r0, r2] + + ldr r2, =CLK_SRC_TOP2_OFFSET + ldr r3, =0x01100000 + str r3, [r0, r2] + + ldr r2, =CLK_SRC_TOP3_OFFSET + ldr r3, =CLK_SRC_TOP3_VAL + ldr r1, [r0, r2] + str r3, [r0, r2] + +@ CMU_TOP MUX / DIV + ldr r1, =CLK_DIV_TOP0_VAL + ldr r2, =CLK_DIV_TOP0_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + + ldr r1, =CLK_DIV_TOP1_VAL + ldr r2, =CLK_DIV_TOP1_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_LEX SRC / DIV + ldr r2, =CLK_SRC_LEX_OFFSET + ldr r3, =CLK_SRC_LEX_VAL + ldr r1, [r0, r2] + orr r1, r1, r3 + str r1, [r0, r2] + ldr r3, =0x1 + bl wait_mux_state + + ldr r1, =CLK_DIV_LEX_VAL + ldr r2, =CLK_DIV_LEX_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_R0X DIV + ldr r1, =CLK_DIV_R0X_VAL + ldr r2, =CLK_DIV_R0X_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_R1X DIV + ldr r1, =CLK_DIV_R1X_VAL + ldr r2, =CLK_DIV_R1X_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@ CMU_CDREX MUX / DIV + ldr r2, =CLK_SRC_CDREX_OFFSET + ldr r3, =0x0 + str r3, [r0, r2] + + ldr r1, =0x71720071 + ldr r2, =CLK_DIV_CDREX_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@CMU_CPU SRC + ldr r2, =CLK_SRC_CPU_OFFSET + ldr r3, =CLK_SRC_CPU_VAL + ldr r1, [r0, r2] + orr r1, r1, r3 + str r1, [r0, r2] + + ldr r2, =CLK_SRC_TOP2_OFFSET + ldr r3, =CLK_SRC_TOP2_VAL + ldr r1, [r0, r2] + orr r1, r1, r3 + str r1, [r0, r2] + + ldr r2, =CLK_SRC_CORE1_OFFSET + ldr r3, =CLK_SRC_CORE1_VAL + ldr r1, [r0, r2] + orr r1, r1, r3 + str r1, [r0, r2] + + ldr r1, =0x66666 + ldr r2, =CLK_SRC_FSYS_OFFSET + str r1, [r0, r2] + + ldr r1, =0x0BB00000 + ldr r2, =CLK_DIV_FSYS0_OFFSET + str r1, [r0, r2] + ldr r3, =0x0 + bl wait_div_state + +@disable CLKOUT_CMU + ldr r1, =0x0 + ldr r2, =CLKOUT_CMU_CPU_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_CORE_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_ACP_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_TOP_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_LEX_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_R0X_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_R1X_OFFSET + str r1, [r0, r2] + + ldr r2, =CLKOUT_CMU_CDREX_OFFSET + str r1, [r0, r2] + + ldr r0, =ELFIN_POWER_BASE +@power down FSYS_ARM + ldr r1, =0x0 + ldr r2, =FSYS_ARM_CONFIGURATION_OFFSET + str r1, [r0, r2] + +@disable SATA_PHY_CONTROL + ldr r1, =0x0 + ldr r2, =SATA_PHY_CONTROL_OFFSET + str r1, [r0, r2] + + @pop {lr} + mov lr, r12 + + bx lr + +ASM_PFX(ArmPlatformTZPCInitialize): + ldr r0, =Exynos5250_TZPC0_BASE + mov r1, #0x0 + str r1, [r0] + mov r1, #0xff + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC1_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC2_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC3_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC4_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC5_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC6_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC7_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC8_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + str r1, [r0, #TZPC_DECPROT2SET_OFFSET] + str r1, [r0, #TZPC_DECPROT3SET_OFFSET] + + ldr r0, =Exynos5250_TZPC9_BASE + str r1, [r0, #TZPC_DECPROT0SET_OFFSET] + str r1, [r0, #TZPC_DECPROT1SET_OFFSET] + + bx lr + +/** + Call at the beginning of the platform boot up + + This function allows the firmware platform to do extra actions at the early + stage of the platform power up. + + Note: This function must be implemented in assembler as there is no stack set up yet + +**/ +ASM_PFX(ArmPlatformSecBootAction): + bx lr + + diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.asm b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.asm new file mode 100644 index 000000000..056a3e7e9 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardBoot.asm @@ -0,0 +1,52 @@ +// +// Copyright (c) 2011, ARM Limited. All rights reserved. +// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// + +#include <AsmMacroIoLib.h> +#include <Base.h> +#include <Library/ArmPlatformLib.h> +#include <AutoGen.h> +#include <ArmPlatform.h> + + INCLUDE AsmMacroIoLib.inc + + EXPORT ArmPlatformSecBootAction + EXPORT ArmPlatformInitializeBootMemory + + PRESERVE8 + AREA RTSMVExpressBootMode, CODE, READONLY + +/** + Call at the beginning of the platform boot up + + This function allows the firmware platform to do extra actions at the early + stage of the platform power up. + + Note: This function must be implemented in assembler as there is no stack set up yet + +**/ +ArmPlatformSecBootAction + bx lr + +/** + Initialize the memory where the initial stacks will reside + + This memory can contain the initial stacks (Secure and Secure Monitor stacks). + In some platform, this region is already initialized and the implementation of this function can + do nothing. This memory can also represent the Secure RAM. + This function is called before the satck has been set up. Its implementation must ensure the stack + pointer is not used (probably required to use assembly language) + +**/ +ArmPlatformInitializeBootMemory + // The SMC does not need to be initialized for RTSM + bx lr diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.S b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.S new file mode 100644 index 000000000..d5858630f --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.S @@ -0,0 +1,96 @@ +# +# Copyright (c) 2012, Sasmsung Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http:#opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# + +#include <AsmMacroIoLib.h> +#include <Base.h> +#include <Library/PcdLib.h> +#include <Library/ArmLib.h> +#include <AutoGen.h> +#.include AsmMacroIoLib.inc + +#include <Chipset/ArmCortexA9.h> + +.text +.align 2 + +GCC_ASM_EXPORT(ArmGetCpuCountPerCluster) +GCC_ASM_EXPORT(ArmPlatformGetCorePosition) +GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore) +GCC_ASM_EXPORT(ArmPlatformPeiBootAction) + +# IN None +# OUT r0 = SCU Base Address +ASM_PFX(ArmGetScuBaseAddress): + # Read Configuration Base Address Register. ArmCBar cannot be called to get + # the Configuration BAR as a stack is not necessary setup. The SCU is at the + # offset 0x0000 from the Private Memory Region. + mrc p15, 4, r0, c15, c0, 0 + bx lr + +# IN None +# OUT r0 = number of cores present in the system +ASM_PFX(ArmGetCpuCountPerCluster): + stmfd SP!, {r1-r2} + + # Read CP15 MIDR + mrc p15, 0, r1, c0, c0, 0 + + # Check if the CPU is A15 + mov r1, r1, LSR #4 + LoadConstantToReg (ARM_CPU_TYPE_MASK, r0) + and r1, r1, r0 + + LoadConstantToReg (ARM_CPU_TYPE_A15, r0) + cmp r1, r0 + beq _Read_cp15_reg + +_CPU_is_not_A15: + mov r2, lr @ Save link register + bl ArmGetScuBaseAddress @ Read SCU Base Address + mov lr, r2 @ Restore link register val + ldr r0, [r0, #A9_SCU_CONFIG_OFFSET] @ Read SCU Config reg to get CPU count + b _Return + +_Read_cp15_reg: + mrc p15, 1, r0, c9, c0, 2 @ Read C9 register of CP15 to get CPU count + lsr r0, #24 + +_Return: + and r0, r0, #3 + # Add '1' to the number of CPU on the Cluster + add r0, r0, #1 + ldmfd SP!, {r1-r2} + bx lr + +ASM_PFX(ArmPlatformIsPrimaryCore): + #last 2 bit of mpid register in 5250 is CPU ID + ldr r1, =0x3 + and r0, r0, r1 + #id for core0 should be 0 + ldr r1, =0x0 + cmp r0, r1 + moveq r0, #1 + movne r0, #0 + mov pc, lr + +ASM_PFX(ArmPlatformGetCorePosition): + and r1, r0, #0x03 //cpu core mask last 2 bits + and r0, r0, #(0x0f<<8) //cpu cluster mask bit 8-11 + add r0, r1, r0, LSR #7 + mov pc, lr + + +ASM_PFX(ArmPlatformPeiBootAction): + mov pc, lr + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.asm b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.asm new file mode 100644 index 000000000..bf81f142a --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardHelper.asm @@ -0,0 +1,73 @@ +// +// Copyright (c) 2011, ARM Limited. All rights reserved. +// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// + +#include <AsmMacroIoLib.h> +#include <Base.h> +#include <Library/PcdLib.h> + +#include <Chipset/ArmCortexA9.h> + +#include <AutoGen.h> + + INCLUDE AsmMacroIoLib.inc + + EXPORT ArmGetCpuCountPerCluster + + AREA RTSMHelper, CODE, READONLY + +// IN None +// OUT r0 = SCU Base Address +ArmGetScuBaseAddress + // Read Configuration Base Address Register. ArmCBar cannot be called to get + // the Configuration BAR as a stack is not necessary setup. The SCU is at the + // offset 0x0000 from the Private Memory Region. + mrc p15, 4, r0, c15, c0, 0 + bx lr + +// IN None +// OUT r0 = number of cores present in the system +ArmGetCpuCountPerCluster + stmfd SP!, {r1-r2} + + // Read CP15 MIDR + mrc p15, 0, r1, c0, c0, 0 + + // Check if the CPU is A15 + mov r1, r1, LSR #4 + mov r0, #ARM_CPU_TYPE_MASK + and r1, r1, r0 + + mov r0, #ARM_CPU_TYPE_A15 + cmp r1, r0 + beq _Read_cp15_reg + +_CPU_is_not_A15 + mov r2, lr ; Save link register + bl ArmGetScuBaseAddress ; Read SCU Base Address + mov lr, r2 ; Restore link register val + ldr r0, [r0, #A9_SCU_CONFIG_OFFSET] ; Read SCU Config reg to get CPU count + b _Return + +_Read_cp15_reg + mrc p15, 1, r0, c9, c0, 2 ; Read C9 register of CP15 to get CPU count + lsr r0, #24 + + +_Return + and r0, r0, #3 + // Add '1' to the number of CPU on the Cluster + add r0, r0, #1 + ldmfd SP!, {r1-r2} + bx lr + + END diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardLib.inf b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardLib.inf new file mode 100755 index 000000000..9ac255abc --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardLib.inf @@ -0,0 +1,69 @@ +#/* @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. +# +#*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BoardLib + FILE_GUID = 736343a0-1d96-11e0-aaaa-0002a5d5c51b + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmPlatformLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec + +[LibraryClasses] + IoLib + ArmLib + MemoryAllocationLib + +[Sources.common] + Board.c + BoardMem.c + BoardHelper.asm | RVCT + BoardHelper.S | GCC + +[Protocols] + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + gArmPlatformTokenSpaceGuid.PcdStandalone + +[FixedPcd] + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + gArmTokenSpaceGuid.PcdFvBaseAddress + + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdFdSize + gArmTokenSpaceGuid.PcdTrustzoneSupport + + gExynosPkgTokenSpaceGuid.PcdTZPCBase + gExynosPkgTokenSpaceGuid.PcdFrameBufferBase + gExynosPkgTokenSpaceGuid.PcdFrameBufferSize + + gExynosPkgTokenSpaceGuid.PcdMpSharedArgsBase + gExynosPkgTokenSpaceGuid.PcdMpSharedArgsSize + + gExynosPkgTokenSpaceGuid.PcdSmemBaseAddress + gExynosPkgTokenSpaceGuid.PcdSmemSize + + gExynosPkgTokenSpaceGuid.PcdiRamBootBase + gExynosPkgTokenSpaceGuid.PcdiRamBootSize + gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferBase +# gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferSize diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardMem.c b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardMem.c new file mode 100755 index 000000000..051776d42 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardMem.c @@ -0,0 +1,221 @@ +/** @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. +* +**/ + +#include <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <ArmPlatform.h> + +// Number of Virtual Memory Map Descriptors without a Logic Tile +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 9 + +// DDR attributes +#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK +#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED +#define DDR_ATTRIBUTES_SECURE_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK +#define DDR_ATTRIBUTES_SECURE_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED + +// Logical Region 1 +#define SOC_REGISTERS_IROM_PHYSICAL_BASE 0x00000000 +#define SOC_REGISTERS_IROM_PHYSICAL_LENGTH 0x02010000 +#define SOC_REGISTERS_IROM_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE +#define SOC_REGISTERS_IROM_SECURE_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_DEVICE + +// Logical Region 2 +#define SOC_REGISTERS_SFR_PHYSICAL_BASE 0x10000000 +#define SOC_REGISTERS_SFR_PHYSICAL_LENGTH 0x08FFFFFF +#define SOC_REGISTERS_SFR_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE +#define SOC_REGISTERS_SFR_SECURE_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_DEVICE + +/** + Return the Virtual Memory Map of your platform + + This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU on your platform. + + @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR describing a Physical-to- + Virtual Memory mapping. This array must be ended by a zero-filled + entry + +**/ +VOID +ArmPlatformGetVirtualMemoryMap ( + IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap + ) +{ + ARM_MEMORY_REGION_ATTRIBUTES CacheAttributes; + UINTN Index = 0; + ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable; + + DEBUG ((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + + UINTN MemoryBase_Pcd = PcdGet32(PcdSystemMemoryBase); + UINTN MemorySize_Pcd = PcdGet32(PcdSystemMemorySize); + UINTN FrameBufferBase_Pcd = PcdGet32(PcdFrameBufferBase); + UINTN FrameBufferSize_Pcd = PcdGet32(PcdFrameBufferSize); + UINTN MpSharedArgsBase_Pcd = PcdGet32(PcdMpSharedArgsBase); + UINTN MpSharedArgsSize_Pcd = PcdGet32(PcdMpSharedArgsSize); + UINTN FdBaseAddress_Pcd = PcdGet32(PcdFdBaseAddress); + UINTN FdSize_Pcd = PcdGet32(PcdFdSize); + UINTN SmemBase_Pcd = PcdGet32(PcdSmemBaseAddress); + UINTN SmemSize_Pcd = PcdGet32(PcdSmemSize); + UINTN iRamBootBase_Pcd = PcdGet32(PcdiRamBootBase); + UINTN iRamBootSize_Pcd = PcdGet32(PcdiRamBootSize); + BOOLEAN TrustzoneSupport_Pcd = PcdGetBool (PcdTrustzoneSupport); + UINT32 Nsacr = ArmReadNsacr(); + UINTN EmmcDMABufferBase_Pcd = PcdGet32(PcdEmmcDMABufferBase); + + // Checking Secure mode + if(Nsacr == 0x0) // Secure mode + { + TrustzoneSupport_Pcd = FALSE; + } + + // Check if SMC TZASC is enabled. If Trustzone not enabled then all the entries remain in Secure World. + // As this value can be changed in the Board Configuration file, the UEFI firmware needs to work for both case + + + ASSERT(VirtualMemoryMap != NULL); + + VirtualMemoryTable = (ARM_MEMORY_REGION_DESCRIPTOR*)AllocatePages(EFI_SIZE_TO_PAGES (sizeof(ARM_MEMORY_REGION_DESCRIPTOR) * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS)); + if (VirtualMemoryTable == NULL) { + return; + } + + if (FeaturePcdGet(PcdCacheEnable) == TRUE) { + CacheAttributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_CACHED : DDR_ATTRIBUTES_SECURE_CACHED); + } else { + CacheAttributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + } + + // FD region : 0x40000000 - 0x40200000 + // Map in the FD region (includes SEC), the stack, and the exception vector region + VirtualMemoryTable[Index].PhysicalBase = FdBaseAddress_Pcd; + VirtualMemoryTable[Index].VirtualBase = FdBaseAddress_Pcd; + VirtualMemoryTable[Index].Length = FdSize_Pcd; // need to check + VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)CacheAttributes; + DEBUG ((EFI_D_ERROR, "FD region : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // SMEM : 0x40200000 - 0x40300000 + // Shared memory 1MB (0x4000_0000 -- 0x4010_0000) + VirtualMemoryTable[++Index].PhysicalBase = SmemBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = SmemBase_Pcd; + VirtualMemoryTable[Index].Length = SmemSize_Pcd; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + DEBUG ((EFI_D_ERROR, "SMEM : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // EMMC : 0x40300000 - 0x40400000 + // EMMC (0x4030_0000 - 0x404_0000) (1MB) + VirtualMemoryTable[++Index].PhysicalBase = EmmcDMABufferBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = EmmcDMABufferBase_Pcd; + VirtualMemoryTable[Index].Length = 0x00100000; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + DEBUG ((EFI_D_ERROR, "EMMC : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + + // DDR : 0x40400000 - 0x4E000000 + // DDR (0x4040_0000 - 0x4E00_0000) (511MB) + VirtualMemoryTable[++Index].PhysicalBase = 0x40400000; + VirtualMemoryTable[Index].VirtualBase = 0x40400000; + VirtualMemoryTable[Index].Length = 0x0DC00000; + VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)CacheAttributes; + DEBUG ((EFI_D_ERROR, "DDR : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // MpParkShared: 0x4D00_0000 - 0x4D10_0000 + // MpParkSahred (0x4D00_0000 - 0x4D10_0000) + VirtualMemoryTable[++Index].PhysicalBase = MpSharedArgsBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = MpSharedArgsBase_Pcd; + VirtualMemoryTable[Index].Length = MpSharedArgsSize_Pcd; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + DEBUG ((EFI_D_ERROR, "FrameBuffer: 0x%8X - 0x%8X\n", VirtualMemoryTable[Index].PhysicalBase, + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // FrameBuffer: 0x4E000000 - 0x50000000 + // Framebuffer (0x4E00_0000 - 0x5000_0000) + VirtualMemoryTable[++Index].PhysicalBase = FrameBufferBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = FrameBufferBase_Pcd; + VirtualMemoryTable[Index].Length = FrameBufferSize_Pcd; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? DDR_ATTRIBUTES_UNCACHED : DDR_ATTRIBUTES_SECURE_UNCACHED); + DEBUG ((EFI_D_ERROR, "FrameBuffer: 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // DDR : 0x50000000 - 0xA0000000 + // DDR (0x5000_0000 - 0x8000_0000) (512MB) + VirtualMemoryTable[++Index].PhysicalBase = MemoryBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = MemoryBase_Pcd; + VirtualMemoryTable[Index].Length = MemorySize_Pcd; + VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)CacheAttributes; + DEBUG ((EFI_D_ERROR, "DDR : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // SFR : 0x10000000 - 0x14000000 + // SFR + VirtualMemoryTable[++Index].PhysicalBase = SOC_REGISTERS_SFR_PHYSICAL_BASE; + VirtualMemoryTable[Index].VirtualBase = SOC_REGISTERS_SFR_PHYSICAL_BASE; + VirtualMemoryTable[Index].Length = SOC_REGISTERS_SFR_PHYSICAL_LENGTH; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? SOC_REGISTERS_SFR_ATTRIBUTES : SOC_REGISTERS_SFR_SECURE_ATTRIBUTES); + DEBUG ((EFI_D_ERROR, "SFR : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // iRAM : 0x02020000 - 0x02040000 + // iRAM + VirtualMemoryTable[++Index].PhysicalBase = iRamBootBase_Pcd; + VirtualMemoryTable[Index].VirtualBase = iRamBootBase_Pcd; + VirtualMemoryTable[Index].Length = iRamBootSize_Pcd; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE : ARM_MEMORY_REGION_ATTRIBUTE_DEVICE); + DEBUG ((EFI_D_ERROR, "iRAM : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // iROM : 0x00000000 - 0x02010000 + // iROM + VirtualMemoryTable[++Index].PhysicalBase = SOC_REGISTERS_IROM_PHYSICAL_BASE; + VirtualMemoryTable[Index].VirtualBase = SOC_REGISTERS_IROM_PHYSICAL_BASE; + VirtualMemoryTable[Index].Length = SOC_REGISTERS_IROM_PHYSICAL_LENGTH; + VirtualMemoryTable[Index].Attributes = (TrustzoneSupport_Pcd ? SOC_REGISTERS_IROM_ATTRIBUTES : SOC_REGISTERS_IROM_SECURE_ATTRIBUTES); + DEBUG ((EFI_D_ERROR, "iROM : 0x%8X - 0x%8X\n", (UINT32)(VirtualMemoryTable[Index].PhysicalBase), + (UINT32)(VirtualMemoryTable[Index].PhysicalBase + VirtualMemoryTable[Index].Length))); + + // End of Table + VirtualMemoryTable[++Index].PhysicalBase = 0; + VirtualMemoryTable[Index].VirtualBase = 0; + VirtualMemoryTable[Index].Length = 0; + VirtualMemoryTable[Index].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)0; + + *VirtualMemoryMap = VirtualMemoryTable; + DEBUG ((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); +} + +/** + Return the EFI Memory Map provided by extension memory on your platform + + This EFI Memory Map of the System Memory is used by MemoryInitPei module to create the Resource + Descriptor HOBs used by DXE core. + TODO: CompleteMe .... say this is the memory not covered by the System Memory PCDs + + @param[out] EfiMemoryMap Array of ARM_SYSTEM_MEMORY_REGION_DESCRIPTOR describing an + EFI Memory region. This array must be ended by a zero-filled entry + +**/ +EFI_STATUS +ArmPlatformGetAdditionalSystemMemory ( + OUT ARM_SYSTEM_MEMORY_REGION_DESCRIPTOR** EfiMemoryMap + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSec.c b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSec.c new file mode 100644 index 000000000..374712722 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSec.c @@ -0,0 +1,52 @@ +/** @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. +* +**/ + +#include <Library/IoLib.h> +#include <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Drivers/PL310L2Cache.h> +#include <Drivers/PL341Dmc.h> + + +/** + Initialize controllers that must setup at the early stage + + Some peripherals must be initialized in Secure World. + For example, some L2x0 requires to be initialized in Secure World + +**/ +VOID +ArmPlatformSecInitialize ( + VOID + ) +{ + return; +} + +/** + Call before jumping to Normal World + + This function allows the firmware platform to do extra actions before + jumping to the Normal World + +**/ +VOID +ArmPlatformSecExtraAction ( + IN UINTN MpId, + OUT UINTN* JumpAddress + ) +{ + *JumpAddress = PcdGet32(PcdFvBaseAddress); +} diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSecLib.inf b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSecLib.inf new file mode 100755 index 000000000..aeaba6eb2 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSecLib.inf @@ -0,0 +1,60 @@ +#/* @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. +# +#*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BoardSecLib + FILE_GUID = 6e02ebe0-1d96-11e0-b9cb-0002a5d5c51b + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmPlatformLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + SamsungPlatformPkg/ExynosPkg/Exynos5250/ExynosPkg.dec + +[LibraryClasses] + IoLib + ArmLib + +[Sources.common] + Board.c + BoardSec.c + mem_init_ddr3.S | GCC + BoardBoot.S | GCC + BoardBoot.asm | RVCT + BoardHelper.asm | RVCT + BoardHelper.S | GCC + +[Protocols] + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + gArmPlatformTokenSpaceGuid.PcdStandalone + +[FixedPcd] + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize + gArmTokenSpaceGuid.PcdFvBaseAddress + + gExynosPkgTokenSpaceGuid.PcdiRamBootBase + gExynosPkgTokenSpaceGuid.PcdiRamBootSize + gExynosPkgTokenSpaceGuid.PcdTZPCBase + + gArmTokenSpaceGuid.PcdFdSize + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdL2x0ControllerBase diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/dmc_init.c b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/dmc_init.c new file mode 100644 index 000000000..297dd6edf --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/dmc_init.c @@ -0,0 +1,787 @@ +/* + * (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. + * + */ + +void dmc_delay(UINT32); +void mem_ctrl_init_done(); + +#define Outp32(addr, data) (*(volatile UINT32 *)(addr) = (data)) +#define Inp32(addr) ((*(volatile UINT32 *)(addr))) + +#define CONFIG_DMC_CALIBRATION +#define CONFIG_ODTOFF_GATELEVELINGON +#define POP_TYPE 1 +#define PRO_PKGINFO 0 + +void DMC_Delay(UINT32 x) +{ + dmc_delay(x); +} + +void CMU_SetMemClk(UINT32 nMEMCLK) +{ + volatile UINT32 uBits; + + // MEM Clock = 800 MHz + + // MCLK_DPHY(0:8), MCLK_CDREX(0:4), BPLL(0:0) + uBits = (0 << 8) | (0 << 4) | (1 << 0); + Outp32(0x10030200, uBits); // rCLK_SRC_CDREX + + // MCLK_DPHY = 800 / 1 = 800 + // MCLK_CDREX = 800 / 1 = 800 + // ACLK_CDREX = MCLK_CDREX / 2 = 400 + // PCLK_CDREX = 800 / 1 / 6 = 133 + + // MCLK_CDREX2(1/1:28), ACLK_SFRTZASCP(1/2:24), MCLK_DPHY(1/1:20), MCLK_CDREX(1/1:16), PCLK_CDREX(1/6:4), ACLK_CDREX(1/2:0) + uBits = (0 << 28) | (1 << 24) | (0 << 20) | (0 << 16) | (5 << 4) | (1 << 0); + Outp32(0x10030500, uBits); // rCLK_DIV_CDREX + + // MPLL(0:8) + uBits = (1 << 8); + Outp32(0x10014204, Inp32(0x10014204) & ~uBits); // rCLK_SRC_CORE1 + + // Setting MPLL [P,M,S] + // + uBits = (1 << 21) | (3 << 12) | (8 << 8); + Outp32(0x10014104, uBits); // rMPLL_CON1 + + // ENABLE(1), MDIV(200), PDIV(3), SDIV(0) + uBits = (1 << 31) | (200 << 16) | (3 << 8) | (0 << 0); // MPLL=1600MHz(3:200:0) + Outp32(0x10014100, uBits); // rMPLL_CON0 + + while ((Inp32(0x10014100) & (1 << 29)) == 0); + + // MPLL(1:8) + uBits = (1 << 8); + Outp32(0x10014204, Inp32(0x10014204) | uBits); // rCLK_SRC_CORE1 + +} + +void DMC_CaTraining(int ch) +{ + unsigned char code; + int find_vmw; + unsigned int phyBase; + unsigned int ioRdOffset; + unsigned int temp, mr41, mr48, vwml, vwmr, vwmc; + unsigned int lock; + unsigned int resp_mr41, resp_mr48; + UINT32 pkg_type = PRO_PKGINFO; + + + phyBase = 0x10c00000+(0x10000 * ch); + ioRdOffset = 0x150 + (0x4 * ch); + + temp = Inp32( phyBase + 0x0000 ); + temp |= (1 << 16); + Outp32( phyBase + 0x0000, temp ); + + temp = Inp32( phyBase + 0x0008 ); + temp |= (1 << 23); + Outp32( phyBase + 0x0008, temp ); + + code = 0x8; + find_vmw = 0; + vwml = vwmr = vwmc = 0; + + if (pkg_type == POP_TYPE) { + resp_mr41 = 0x5555; + resp_mr48 = 0x0101; + } else { + if ( ch == 0 ) { + resp_mr41 = 0x69C5; + resp_mr48 = 0x4040; + } else { + resp_mr41 = 0xD14E; + resp_mr48 = 0x8008; + } + } + + while (1) { + + //- code update + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFFFFFF00; + temp |= code; + Outp32( phyBase + 0x0028, temp ); + + //- resync + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFEFFFFFF; + Outp32( phyBase + 0x0028, temp ); + temp |= 0x01000000; + Outp32( phyBase + 0x0028, temp ); + temp &= 0xFEFFFFFF; + Outp32( phyBase + 0x0028, temp ); + + if(ch == 0) { + Outp32( 0x10DD0000+0x0010, 0x50690 ); //- Send MRW: MA=0x29 OP=0xA4, 0x50690 + //Outp32( 0x10DD0000+0x0010, 0x001050690 ); //- Send MRW: MA=0x29 OP=0xA4, 0x50690 + } else { + Outp32( 0x10DD0000+0x0010, 0x10050690 ); //- Send MRW: MA=0x29 OP=0xA4, 0x10050690 + //Outp32( 0x10DD0000+0x0010, 0x10150690 ); //- Send MRW: MA=0x29 OP=0xA4, 0x10050690 + } + + Outp32( 0x10DD0000+0x0160, 0x3FF011 ); //- Set DMC.CACAL_CONFIG0.deassert_cke=1 + Outp32( 0x10DD0000+0x0164, 0x1 ); //- Set DMC.CACAL_CONFIG1.cacal_csn=1 + DMC_Delay(0x100); + + mr41 = Inp32( 0x10DD0000 + ioRdOffset ); + mr41 &= 0xFFFF; + + Outp32( 0x10DD0000+0x0160, 0x3FF010 ); //- Set DMC.CACAL_CONFIG0.deassert_cke=0 + DMC_Delay(0x100); + + if( ch == 0 ) { + Outp32( 0x10DD0000+0x0010, 0x60300 ); //- Send MRW: MA=0x30 OP=0xC0, 0x60300 + //Outp32( 0x10DD0000+0x0010, 0x001060300 ); //- Send MRW: MA=0x30 OP=0xC0, 0x60300 + } else { + Outp32( 0x10DD0000+0x0010, 0x10060300 ); //- Send MRW: MA=0x30 OP=0xC0, 0x10060300 + //Outp32( 0x10DD0000+0x0010, 0x10160300 ); //- Send MRW: MA=0x30 OP=0xC0, 0x10060300 + } + + Outp32( 0x10DD0000+0x0160, 0x3FF011 ); //- Set DMC.CACAL_CONFIG0.deassert_cke=1 + Outp32( 0x10DD0000+0x0164, 0x1 ); //- Set DMC.CACAL_CONFIG1.cacal_csn=1 + DMC_Delay(0x100); + + mr48 = Inp32( 0x10DD0000 + ioRdOffset ); + + if (pkg_type == POP_TYPE) { + mr48 &= 0x0303; + } else { + if ( ch == 0 ) { + mr48 &= 0xC060; + } else { + mr48 &= 0x8418; + } + } + + Outp32( 0x10DD0000+0x0160, 0x3FF010 ); //- Set DMC.CACAL_CONFIG0.deassert_cke=0 + DMC_Delay(0x100); + + if( (find_vmw == 0) && (mr41 == resp_mr41 ) && ( mr48 == resp_mr48 ) ) { + find_vmw = 0x1; + vwml = code; + } + + if( (find_vmw == 1) && ( (mr41 != resp_mr41 ) || ( mr48 != resp_mr48 ) ) ) { + find_vmw = 0x3; + vwmr = code - 1; + + if( ch == 0 ) { + Outp32( 0x10DD0000+0x0010, 0x50AA0 ); //- Send MRW: MA=0x2A OP=0xA8, 0x50AA0 + //Outp32( 0x10DD0000+0x0010, 0x001050AA0 ); //- Send MRW: MA=0x2A OP=0xA8, 0x50AA0 + } else { + Outp32( 0x10DD0000+0x0010, 0x10050AA0 ); //- Send MRW: MA=0x2A OP=0xA8, 0x50AA0 + //Outp32( 0x10DD0000+0x0010, 0x10150AA0 ); //- Send MRW: MA=0x2A OP=0xA8, 0x50AA0 + } + //DMC_Delay(0x10000); + break; + } + + code++; + + if(code == 255) { + while(1); + } + } + + vwmc = (vwml + vwmr) / 2; + +#if 1 + { + UINT32 lock_force; + UINT32 temp = 0; + + lock_force = (Inp32( phyBase + 0x30 ) >> 8) & 0x7F; + + temp = ((vwml & 0xFF) << 16) | + ((vwmr & 0xFF) << 8) | + ((vwmc & 0xFF)); + + if(ch == 0) { + Outp32(0x10040818, temp); + } + else { + Outp32(0x1004081C, temp); + } + } +#endif + + //- code update + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFFFFFF00; + temp |= vwmc; + Outp32( phyBase + 0x0028, temp ); + + //- resync + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFEFFFFFF; + Outp32( phyBase + 0x0028, temp ); + temp |= 0x01000000; + Outp32( phyBase + 0x0028, temp ); + temp &= 0xFEFFFFFF; + Outp32( phyBase + 0x0028, temp ); + + temp = Inp32( phyBase+0x0000 ); + temp &= 0xFFFEFFFF; + Outp32( phyBase + 0x0000, temp ); + +#if 1 + + //- vmwc convert to offsetd value. + + lock = Inp32( phyBase + 0x0034 ); + lock &= 0x1FF00; + lock >>= 8; + + if( (lock & 0x3) == 0x3 ) { + lock++; + } + + code = vwmc - (lock >> 2); + + temp = Inp32( phyBase + 0x0028 ); + temp &= 0xFFFFFF00; + temp |= code; + Outp32( phyBase + 0x0028, temp ); + + temp = Inp32( phyBase + 0x0008 ); + temp &= 0xFF7FFFFF; + Outp32( phyBase + 0x0008, temp ); +#endif +} + +static void DMC_ZqInit(UINT8 dq, UINT8 ck, UINT8 cke, UINT8 cs, UINT8 ca) +{ + UINT32 temp; + UINT32 zqBase; + int ch; + + for( ch = 0; ch < 2; ch++ ) { + + zqBase = 0x10c00000 + ( 0x10000 * ch ); + + temp = Inp32( zqBase + 0x40 ); + temp &= 0xF8FBFFF1; + temp |= ( ( dq & 0x7 ) << 24 ); + temp |= ( ( 1 << 18 ) | ( 1 << 2 ) ); + + Outp32( zqBase + 0x40, temp ); + + temp |= (1 << 1); + + Outp32( zqBase + 0x40, temp ); + + while( ( Inp32( zqBase + 0x48 ) & 0x5 ) != 0x1 ); + + temp = Inp32( zqBase + 0x40 ); + + temp &= ~( 1 << 18 ); + + Outp32( zqBase + 0x40, temp ); + + temp = ( ( ck & 0x7 ) << 9 ) | ( ( cke & 0x7 ) << 6 ) | + ( ( cs & 0x7 ) << 3 ) | ( ca & 0x7 ); + + Outp32( zqBase + 0xA0, temp ); + } +} + +void mem_ctrl_init_lpddr3(UINT32 nMEMCLK) +{ + UINT32 lock, temp; + UINT32 pkg_type = PRO_PKGINFO; + + //- + //-PHASE 1 : PHY DLL Initialization + //- + //-2) Set the right value to PHY_CON0.ctrl_ddr_mode + Outp32( 0x10C00000+0x0000, 0x17021A40 ); //- PHY0.CON0[12:11].ctrl_ddr_mode=LPDDR3 + Outp32( 0x10C10000+0x0000, 0x17021A40 ); //- PHY1.CON0[12:11].ctrl_ddr_mode=LPDDR3 + //-3) Enable CA swap when POP is used + Outp32( 0x10C00000+0x0000, 0x17021A00 ); //- PHY0.CON0.ctrl_atgate=0x0 + Outp32( 0x10C10000+0x0000, 0x17021A00 ); //- PHY1.CON0.ctrl_atgate=0x0 + + if (pkg_type == POP_TYPE) { + Outp32( 0x10030A20, 0x80000000 ); //- LPDDR3PHY_CON3[31]=1. + Outp32( 0x10C00000+0x0064, 0x1 ); //- PHY0.CON24[0]=1 + Outp32( 0x10C10000+0x0064, 0x1 ); //- PHY0.CON24[0]=1 + } else { + Outp32( 0x10030A20, 0x00000000 ); //- LPDDR3PHY_CON3[31]=0. + Outp32( 0x10C00000+0x0064, 0x0 ); //- PHY0.CON24[0]=0 + Outp32( 0x10C10000+0x0064, 0x0 ); //- PHY0.CON24[0]=0 + } + //-4) Set PHY for DQS pull-down mode + Outp32( 0x10C00000+0x0038, 0x0F ); //- PHY0.CON14.ctrl_pulld_dq=0x0, ctrl_pulld_dqs=0x0F + Outp32( 0x10C10000+0x0038, 0x0F ); //- PHY1.CON14.ctrl_pulld_dq=0x0, ctrl_pulld_dqs=0x0F + //-5) Set PHY_CON42.ctrl_bstlen and PHY_CON42.ctrl_rdlat + Outp32( 0x10C00000+0x00ac, 0x80C ); //- PHY0.CON42.ctrl_bstlen[12:8]=0x8, ctrl_rdlat[4:0]=0x0C + Outp32( 0x10C10000+0x00ac, 0x80C ); //- PHY1.CON42.ctrl_bstlen[12:8]=0x8, ctrl_rdlat[4:0]=0x0C + Outp32( 0x10C00000+0x006C, 0x7107F ); //- PHY0.CON26.T_wrdata_en[20:16]=0x7 + Outp32( 0x10C10000+0x006C, 0x7107F ); //- PHY1.CON26.T_wrdata_en[20:16]=0x7 + Outp32( 0x10C00000+0x0000, 0x17021A00 ); //- Set PHY0.PHY_CON0.ctrl_read_disable=0x0 + Outp32( 0x10C00000+0x0040, 0x8080304 ); //- Set PHY0.PHY_CON16.zq_term. + Outp32( 0x10C10000+0x0000, 0x17021A00 ); //- Set PHY1.PHY_CON0.ctrl_read_disable=0x0 + Outp32( 0x10C10000+0x0040, 0x8080304 ); //- Set PHY1.PHY_CON16.zq_term. + Outp32( 0x10030B00, 0x1 ); //- Set 0x1003_0B00[0]=0x1 + //-6) ZQ calibration + if (pkg_type == POP_TYPE) { + Outp32( 0x10C00000+0x0040, 0xE0C0304 ); //- Set PHY0.CON16.zq_mode_dds=0x6000000 + Outp32( 0x10C00000+0x0040, 0xE0C0304 ); //- Set PHY0.CON16.zq_manual_mode=1 + Outp32( 0x10C00000+0x0040, 0xE0C0306 ); //- Set PHY0.CON16.zq_manual_str + while( ( Inp32( 0x10C00000+0x0048 ) & 0x1 ) != 0x1 ); //- Wait for PHY0.CON17.zq_done + Outp32( 0x10C00000+0x0040, 0xE080304 ); //- Set PHY0.CON16.zq_clk_en=0 + Outp32( 0x10C10000+0x0040, 0xE0C0304 ); //- Set PHY1.CON16.zq_mode_dds=0x6000000 + Outp32( 0x10C10000+0x0040, 0xE0C0304 ); //- Set PHY1.CON16.zq_manual_mode=1 + Outp32( 0x10C10000+0x0040, 0xE0C0306 ); //- Set PHY1.CON16.zq_manual_str + while( ( Inp32( 0x10C10000+0x0048 ) & 0x1 ) != 0x1 ); //- Wait for PHY1.CON17.zq_done + Outp32( 0x10C10000+0x0040, 0xE080304 ); //- Set PHY1.CON16.zq_clk_en=0 + Outp32( 0x10C00000+0x00A0, 0xDB6 ); //- PHY0.CON39[11:0]=0xDB6 + Outp32( 0x10C10000+0x00A0, 0xDB6 ); //- PHY1.CON39[11:0]=0xDB6 + } else { + DMC_ZqInit(0x4, 0x4, 0x4, 0x4, 0x4); + } + + //-7) Set CONCONTROL. At this moment, assert the dfi_init_start field to high. + Outp32( 0x10DD0000+0x0000, 0xFFF2100 ); //- rdfetch=0x2 + Outp32( 0x10DD0000+0x0000, 0x1FFF2100 ); //- assert dfi_init_start + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0000, 0xFFF2100 ); //- deassert dfi_init_start + //- + //-PHASE 2 : Setting Controller Register + //- + //-8) Set MEMCONTROL. At this moment, switch OFF all low power feature. + Outp32( 0x10DD0000+0x0004, 0x312700 ); //- memcontrol + //-9) Set the MEMBASECONFIG0 register. + //- If there are two external memory chips set the MEMBASECONFIG1 register. + Outp32( 0x10DD0000+0x010C, 0x4007C0 ); //- chipbase0=0x40, mask=0x7C0 + Outp32( 0x10DD0000+0x0110, 0x8007C0 ); //- chipbase1=0x80, mask=0x7C0 + Outp32( 0x10DD0000+0x0008, 0x1323 ); //- memconfig0 + Outp32( 0x10DD0000+0x000C, 0x1323 ); //- memconfig1 + //-10) Set the PRECHCONFIG register + Outp32( 0x10DD0000+0x0014, 0xFF000000 ); //- DMC.PRECHCONFIG[15:0]=(0x0|0x0) + //-11) Set the TIMINGAREF, TIMINGROW, TIMINGDATA, and TIMINGPOWER registers + //- according to memory AC parameters. + Outp32( 0x10DD0000+0x00F0, 0x7 ); //- iv_size=0x7 + Outp32( 0x10DD0000+0x0030, 0x5D ); //- tREFI=0x5D + Outp32( 0x10DD0000+0x0034, 0x34498692 ); //- DMC.TIMINGROW=0x34498692 + Outp32( 0x10DD0000+0x0038, 0x3630560C ); //- DMC.TIMINGDATA=0x3630560C + Outp32( 0x10DD0000+0x003C, 0x50380336 ); //- DMC.TIMINGPOWER=0x50380336 + Outp32( 0x10DD0000+0x0004, 0x312700 ); //- + //-12) Set the QOSCONTROL0~15 and BRBQOSCONFIG register if Qos Scheme is required. + Outp32( 0x10DD0000+0x60, 0xFFF ); //- QOS#0.=0xFFF + Outp32( 0x10DD0000+0x68, 0xFFF ); //- QOS#1.=0xFFF + Outp32( 0x10DD0000+0x70, 0xFFF ); //- QOS#2.=0xFFF + Outp32( 0x10DD0000+0x78, 0xFFF ); //- QOS#3.=0xFFF + Outp32( 0x10DD0000+0x80, 0xFFF ); //- QOS#4.=0xFFF + Outp32( 0x10DD0000+0x88, 0xFFF ); //- QOS#5.=0xFFF + Outp32( 0x10DD0000+0x90, 0xFFF ); //- QOS#6.=0xFFF + Outp32( 0x10DD0000+0x98, 0xFFF ); //- QOS#7.=0xFFF + Outp32( 0x10DD0000+0xA0, 0xFFF ); //- QOS#8.=0xFFF + Outp32( 0x10DD0000+0xA8, 0xFFF ); //- QOS#9.=0xFFF + Outp32( 0x10DD0000+0xB0, 0xFFF ); //- QOS#10.=0xFFF + Outp32( 0x10DD0000+0xB8, 0xFFF ); //- QOS#11.=0xFFF + Outp32( 0x10DD0000+0xC0, 0xFFF ); //- QOS#12.=0xFFF + Outp32( 0x10DD0000+0xC8, 0xFFF ); //- QOS#13.=0xFFF + Outp32( 0x10DD0000+0xD0, 0xFFF ); //- QOS#14.=0xFFF + Outp32( 0x10DD0000+0xD8, 0x0 ); //- QOS#15.=0xFFF + //-13) Set the PHY_CON4.ctrl_offsetr0~3 and PHY_CON6.ctrl_offsetw0~3 to 0x7F. + Outp32( 0x10C00000+0x0010, 0x7F7F7F7F ); //- offsetr=0:0x7F, 1:0x7F, 2:0x7F, 3:0x7F + Outp32( 0x10C10000+0x0010, 0x7F7F7F7F ); //- offsetr=0:0x7F, 1:0x7F, 2:0x7F, 3:0x7F + Outp32( 0x10C00000+0x0018, 0x7F7F7F7F ); //- offsetw=0:0x7F, 1:0x7F, 2:0x7F, 3:0x7F + Outp32( 0x10C10000+0x0018, 0x7F7F7F7F ); //- offsetw=0:0x7F, 1:0x7F, 2:0x7F, 3:0x7F + //-14) Set the PHY_CON4.ctrl_offsetd value to 0x7F. + Outp32( 0x10C00000+0x0028, 0x7F ); //- offsetd=0x7F + Outp32( 0x10C10000+0x0028, 0x7F ); //- offsetd=0x7F + //-15) + //-16) + Outp32( 0x10C00000+0x0030, 0x10107F70 ); //- lock forcing=0x7F + Outp32( 0x10C10000+0x0030, 0x10107F70 ); //- lock forcing=0x7F + Outp32( 0x10C00000+0x0030, 0x10107F50 ); //- disable ctrl_dll_on + Outp32( 0x10C10000+0x0030, 0x10107F50 ); //- disable ctrl_dll_on + DMC_Delay(0x100); //- wait 1ms + //-18) Update the DLL information. + Outp32( 0x10DD0000+0x0018, 0x8 ); //- fp_resync=1 + Outp32( 0x10DD0000+0x0018, 0x0 ); //- fp_resync=0 + //- + //-PHASE 3 : Memory Initialization + //- + //-18)~26) + Outp32( 0x10DD0000+0x0010, 0x7000000 ); //- port:0x0, cs:0x0 nop command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x71C00 ); //- port:0x0, cs:0x0 mr63 command + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0010, 0x10BFC ); //- port:0x0, cs:0x0 mr10 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x50C ); //- port:0x0, cs:0x0 mr1 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x868 ); //- port:0x0, cs:0x0 mr2 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0xC04 ); //- port:0x0, cs:0x0 mr3 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x7100000 ); //- port:0x0, cs:0x1 nop command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x171C00 ); //- port:0x0, cs:0x1 mr63 command + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0010, 0x110BFC ); //- port:0x0, cs:0x1 mr10 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10050C ); //- port:0x0, cs:0x1 mr1 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x100868 ); //- port:0x0, cs:0x1 mr2 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x100C04 ); //- port:0x0, cs:0x1 mr3 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x17000000 ); //- port:0x1, cs:0x0 nop command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10071C00 ); //- port:0x1, cs:0x0 mr63 command + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0010, 0x10010BFC ); //- port:0x1, cs:0x0 mr10 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x1000050C ); //- port:0x1, cs:0x0 mr1 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10000868 ); //- port:0x1, cs:0x0 mr2 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10000C04 ); //- port:0x1, cs:0x0 mr3 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x17100000 ); //- port:0x1, cs:0x1 nop command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10171C00 ); //- port:0x1, cs:0x1 mr63 command + DMC_Delay(0x10000); //- wait 100ms + Outp32( 0x10DD0000+0x0010, 0x10110BFC ); //- port:0x1, cs:0x1 mr10 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x1010050C ); //- port:0x1, cs:0x1 mr1 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10100868 ); //- port:0x1, cs:0x1 mr2 command + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10DD0000+0x0010, 0x10100C04 ); //- port:0x1, cs:0x1 mr3 command + DMC_Delay(0x100); //- wait 1ms + //-27) Return to the memory operating frequency. + CMU_SetMemClk(800); + + //-28) Set the PHY_CON4.ctrl_offsetr0~3 and PHY_CON6.ctrl_offsetw0~3 to 0x8. + Outp32( 0x10C00000+0x0010, 0x8080808 ); //- offsetr=0:0x08, 1:0x08, 2:0x08, 3:0x08 + Outp32( 0x10C10000+0x0010, 0x8080808 ); //- offsetr=0:0x08, 1:0x08, 2:0x08, 3:0x08 + Outp32( 0x10C00000+0x0018, 0x8080808 ); //- offsetw=0:0x08, 1:0x08, 2:0x08, 3:0x08 + Outp32( 0x10C10000+0x0018, 0x8080808 ); //- offsetw=0:0x08, 1:0x08, 2:0x08, 3:0x08 + //-29) Set the PHY_CON4.ctrl_offsetd value to 0x8. + Outp32( 0x10C00000+0x0028, 0x8 ); //- offsetd=0x08 + Outp32( 0x10C10000+0x0028, 0x8 ); //- offsetd=0x08 + //-30)~34) + Outp32( 0x10C00000+0x0030, 0x10107F70 ); //- ctrl_dll_on[5] = 1 + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10C00000+0x0030, 0x10107F30 ); //- ctrl_start[6] = 0 + Outp32( 0x10C00000+0x0030, 0x10107F70 ); //- ctrl_start[6] = 1 + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10C10000+0x0030, 0x10107F70 ); //- ctrl_dll_on[5] = 1 + DMC_Delay(0x100); //- wait 1ms + Outp32( 0x10C10000+0x0030, 0x10107F30 ); //- ctrl_start[6] = 0 + Outp32( 0x10C10000+0x0030, 0x10107F70 ); //- ctrl_start[6] = 1 + DMC_Delay(0x100); //- wait 1ms + //-35)~36) + Outp32( 0x10DD0000+0x0000, 0x1FFF2100 ); //- assert dfi_init_start + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC ) != 0xC ); //- Wait for DMC.dfi_init_complete_ch0/1 + Outp32( 0x10DD0000+0x0000, 0xFFF2100 ); //- deassert dfi_init_start + //-37) Update the DLL information. + Outp32( 0x10DD0000+0x0018, 0x8 ); //- fp_resync=1 + Outp32( 0x10DD0000+0x0018, 0x0 ); //- fp_resync=0 + +#if defined(CONFIG_DMC_CALIBRATION) + //-38) Do leveing and calibration + //-39) Perform these steps + //- - a. Update PHYCON12.ctrl_force with by using PHY_CON13.ctrl_lock_value[9:2] + lock = (Inp32(0x10c00034) >> 8) & 0xFF; + if((lock & 0x3) == 0x3) { + lock++; + } + + temp = Inp32(0x10c00030) & 0xFFFF80FF; + temp |= ((lock >> 2) << 8); + Outp32( 0x10c00000 + 0x0030, temp); + + lock = (Inp32(0x10c10034) >> 8) & 0xFF; + if((lock & 0x3) == 0x3) { + lock++; + } + + temp = Inp32(0x10c10030) & 0xFFFF80FF; + temp |= ((lock >> 2) << 8); + Outp32( 0x10c10000 + 0x0030, temp); + + //- - b. Enable PHY_CON0.ctrl_atgate + Outp32( 0x10C00000+0x0000, 0x17021A40 ); //- PHY0.CON0.ctrl_atgate=1. + Outp32( 0x10C10000+0x0000, 0x17021A40 ); //- PHY1.CON0.ctrl_atgate=1. + //- - d. Enable PHY_CON0.p0_cmd_en + Outp32( 0x10C00000+0x0000, 0x17025A40 ); //- PHY0.CON0.p0_cmd_en=1. + Outp32( 0x10C10000+0x0000, 0x17025A40 ); //- PHY1.CON0.p0_cmd_en=1. + //- - e. Enable PHY_CON2.InitDeskewEn + Outp32( 0x10C00000+0x0008, 0x10044 ); //- PHY0.CON2.InitDeskewEn=1. + Outp32( 0x10C10000+0x0008, 0x10044 ); //- PHY1.CON2.InitDeskewEn=1. + //- - f. Enable PHY_CON0.byte_rdlvl_en + Outp32( 0x10C00000+0x0000, 0x17027A40 ); //- + Outp32( 0x10C10000+0x0000, 0x17027A40 ); //- + + //- - c. Disable PHY_CON12.ctrl_dll_on + temp = Inp32(0x10c00030) & 0xFFFFFFDF; + Outp32( 0x10c00030, temp ); + temp = Inp32(0x10c10030) & 0xFFFFFFDF; + Outp32( 0x10c10030, temp ); + DMC_Delay(0x100); //- wait 1ms + + //-CA Training. + DMC_CaTraining(0); + DMC_CaTraining(1); + + if (pkg_type == POP_TYPE) { + //-Read DQ Calibration. + Outp32( 0x10C00000+0x0004, 0x92F0001 ); //- Set PHY0.CON1.rdlvl_rddata_adj + Outp32( 0x10C10000+0x0004, 0x92F0001 ); //- Set PHY1.CON1.rdlvl_rddata_adj + Outp32( 0x10C00000+0x005C, 0x00000041 ); //- PHY0.CON22.lpddr2_addr=0x041 + Outp32( 0x10C10000+0x005C, 0x00000041 ); //- PHY1.CON22.lpddr2_addr=0x041 + Outp32( 0x10C00000+0x0008, 0x2010044 ); //- Set PHY0.CON2.rdlvl_en + Outp32( 0x10C10000+0x0008, 0x2010044 ); //- Set PHY1.CON2.rdlvl_en + Outp32( 0x10DD0000+0x00F8, 0x2 ); //- DMC.RDLVLCONFIG.ctrl_rdlvl_data_en=1 + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC000 ) != 0xC000 ); //- Wait DMC.rdlvl_complete_ch0/1 + Outp32( 0x10DD0000+0x00F8, 0x0 ); //- Set DMC.RDLVLCONFIG.ctrl_rdlvl_data_en=0 + + Outp32(0x10C00000 + 0x0014, 0xC); + while( Inp32(0x10C00000 + 0x0058) != 0); + + Outp32(0x10C10000 + 0x0014, 0xC); + while( Inp32(0x10C00000 + 0x0058) != 0); + + Outp32(0x10C00000 + 0x0014, 0x0); + Outp32(0x10C10000 + 0x0014, 0x0); + + //-Write DQ Calibration. + while( ( Inp32( 0x10DD0000+0x0048 ) & 0x3 ) != 0x0 ); //- Wait for DMC.chip_busy_state CH0 + while( ( Inp32( 0x10DD0000+0x004C ) & 0x3 ) != 0x0 ); //- Wait for DMC.chip_busy_state CH1 + Outp32( 0x10DD0000+0x00F4, 0x1 ); //- DMC.WRTRACONFIG + Outp32( 0x10C00000+0x005C, 0x204 ); //- + Outp32( 0x10C10000+0x005C, 0x204 ); //- + Outp32( 0x10C00000+0x0004, 0x92F00FF ); //-Set "rdlvl_rddata_adj" to 0x0001 or 0x0100 in PHY_CON1[15:0] + Outp32( 0x10C10000+0x0004, 0x92F00FF ); //-Set "rdlvl_rddata_adj" to 0x0001 or 0x0100 in PHY_CON1[15:0] + Outp32( 0x10C00000+0x0008, 0x6010044 ); //- + Outp32( 0x10C10000+0x0008, 0x6010044 ); //- + Outp32( 0x10C00000+0x0008, 0xE010044 ); //- + Outp32( 0x10C10000+0x0008, 0xE010044 ); //- + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC000 ) != 0xC000 ); //- Wait DMC.rdlvl_complete_ch0/1 + Outp32( 0x10C00000+0x0008, 0x6010044 ); //- + Outp32( 0x10C10000+0x0008, 0x6010044 ); //- + + Outp32(0x10C00000 + 0x0014, 0xC); + while( Inp32(0x10C00000 + 0x0058) != 0); + + Outp32(0x10C10000 + 0x0014, 0xC); + while( Inp32(0x10C10000 + 0x0058) != 0); + + Outp32(0x10C00000 + 0x0014, 0x0); + Outp32(0x10C10000 + 0x0014, 0x0); + } + + //-43) Enable PHY_CON12.ctrl_dll_on + temp = Inp32( 0x10c00030) | 0x20; + Outp32( 0x10c00030, temp ); + //while( ( Inp32(0x10c00030) & 0x1 ) != 0x1 ); + + temp = Inp32( 0x10c10030) | 0x20; + Outp32( 0x10c10030, temp ); + //while( ( Inp32(0x10c10030) & 0x1 ) != 0x1 ); + + //-44) Disable PHY_CON.ctrl_atgate when POP is used + if (pkg_type == POP_TYPE) { + Outp32( 0x10C00000+0x0000, 0x17027A00 ); //- PHY0.CON0.ctrl_atgate=0x0 + Outp32( 0x10C10000+0x0000, 0x17027A00 ); //- PHY1.CON0.ctrl_atgate=0x0 + } + Outp32( 0x10C00000+0x0000, 0x17127A00 ); //- Set PHY0.CON0.ctrl_upd_range=0x1 + Outp32( 0x10C10000+0x0000, 0x17127A00 ); //- Set PHY1.CON0.ctrl_upd_range=0x1 + + //-45) Enable PHY_CON2.DLLDeSkewEn + if (pkg_type == POP_TYPE) { + Outp32( 0x10C00000+0x0008, 0x6011044 ); //- PHY0.CON2.DllDeskewEn=1. + Outp32( 0x10C10000+0x0008, 0x6011044 ); //- PHY1.CON2.DllDeskewEn=1. + } else { + Outp32( 0x10C00000+0x0008, 0x11044 ); //- PHY0.CON2.DllDeskewEn=1. + Outp32( 0x10C10000+0x0008, 0x11044 ); //- PHY1.CON2.DllDeskewEn=1. + } + //-46) Update the DLL information + Outp32( 0x10DD0000+0x0018, 0x8 ); //- fp_resync=1 + Outp32( 0x10DD0000+0x0018, 0x0 ); //- fp_resync=0 +#endif + + //-47) ODT is not supported in LPDDR2/LPDDR3 + if (pkg_type == POP_TYPE) { + Outp32( 0x10C00000+0x0000, 0x17127A00 ); //- Set PHY0.PHY_CON0.ctrl_read_disable=0x0 + Outp32( 0x10C00000+0x0040, 0xE080304 ); //- Set PHY0.PHY_CON16.zq_term. + Outp32( 0x10C10000+0x0000, 0x17127A00 ); //- Set PHY1.PHY_CON0.ctrl_read_disable=0x0 + Outp32( 0x10C10000+0x0040, 0xE080304 ); //- Set PHY1.PHY_CON16.zq_term. + } + + //-48) Issue the PALL command to memory + Outp32( 0x10DD0000+0x0010, 0x1000000 ); //- send PALL to port=0x0, cs=0x0 + Outp32( 0x10DD0000+0x0010, 0x1100000 ); //- send PALL to port=0x0, cs=0x1 + Outp32( 0x10DD0000+0x0010, 0x11000000 ); //- send PALL to port=0x1, cs=0x0 + Outp32( 0x10DD0000+0x0010, 0x11100000 ); //- send PALL to port=0x1, cs=0x1 + //-49) Set the MEMCONTROL if power-down modes are required. + Outp32( 0x10DD0000+0x0004, 0x312700 ); //- DMC.MEMCONTROL.tp_en=0x0. + Outp32( 0x10DD0000+0x0014, 0xFF000000 ); //- DMC.PRECHCONFIG.tp_cnt=0xFF + Outp32( 0x10DD0000+0x0028, 0xFFFF00FF ); //- DMC.PWRDNCONFIG.dsref_cyc=0xFFFF0000 + Outp32( 0x10DD0000+0x0004, 0x312720 ); //- Set DMC.MEMCONTROL.dsref_en=0x20. + Outp32( 0x10DD0000+0x0028, 0xFFFF00FF ); //- Set DMC.PWRDNCONFIG.dpwrdn_cyc=0xFF + Outp32( 0x10DD0000+0x0004, 0x312722 ); //- Set DMC.MEMCONTROL.dpwrdn_en=0x2., dpwrdn_type=0x0 + Outp32( 0x10DD0000+0x0004, 0x312723 ); //- DMC.MEMCONTROL.clk_stop_en=0x1. + Outp32( 0x10DD0000+0x0000, 0xFFF2108 ); //- Set DMC.PHYCONTROL.io_pd_con=0x1. + //-50) Set the CONCONTROL to turn on an auto refresh counter. + Outp32( 0x10DD0000+0x0000, 0xFFF2128 ); //- aref enabled + + mem_ctrl_init_done(); + +} + +void mem_ctrl_init_ddr3(UINT32 nMEMCLK) +{ + UINT32 ap_odt, dram_odt; + +#if defined(CONFIG_ODTOFF_GATELEVELINGON) + ap_odt = 0xE2C0000; + dram_odt = 0x2; +#else // ODT On and Gate Leveling Off + ap_odt = 0xE240000; + dram_odt = 0x42; +#endif + + CMU_SetMemClk(nMEMCLK); + + DMC_Delay(0x10000); // wait 300ms + Outp32( 0x10030A10, 0x00000000 ); //- PHY_RESET[0]=0 + DMC_Delay(100); + Outp32( 0x10030A10, 0x00000001 ); //- PHY_RESET[0]=1 + DMC_Delay(100); + Outp32( 0x10C00000+0x00a0, 0x000006db ); //- dds of CA = 0x3 + Outp32( 0x10C10000+0x00a0, 0x000006db ); //- dds of CA = 0x3 + Outp32( 0x10C00000+0x00ac, 0x0000080b ); //- ctrl_bstlen[12:8]=8, ctrl_rdlat[4:0]=11 + Outp32( 0x10C10000+0x00ac, 0x0000080b ); //- ctrl_bstlen[12:8]=8, ctrl_rdlat[4:0]=11 + Outp32( 0x10C00000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_clk_div_en[18]=1 + Outp32( 0x10C10000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_clk_div_en[18]=1 + Outp32( 0x10C00000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_mode_noterm[19]=0 + Outp32( 0x10C10000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_mode_noterm[19]=0 + Outp32( 0x10C00000+0x0040, ap_odt|0x0306 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=1 + Outp32( 0x10C10000+0x0040, ap_odt|0x0306 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=1 + while( ( Inp32( 0x10C00000+0x0048 ) & 0x1 ) != 0x1 ); //- PHY0: wait for zq_done + while( ( Inp32( 0x10C10000+0x0048 ) & 0x1 ) != 0x1 ); //- PHY1: wait for zq_done + Outp32( 0x10C00000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=0 + Outp32( 0x10C10000+0x0040, ap_odt|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=0 + Outp32( 0x10C00000+0x0038, 0x0000000f ); //- ctrl_pulld_dq[11:8]=0xf, ctrl_pulld_dqs[3:0]=0xf + Outp32( 0x10C10000+0x0038, 0x0000000f ); //- ctrl_pulld_dq[11:8]=0xf, ctrl_pulld_dqs[3:0]=0xf + Outp32( 0x10DD0000+0x0000, 0x1FFF0000|(0x3<<12) ); //- dfi_init_start[28]=1, rd_fetch[14:12]=3 + Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + Outp32( 0x10C00000+0x0010, 0x8080808 ); //- ctrl_offsetr + Outp32( 0x10C10000+0x0010, 0x8080808 ); //- ctrl_offsetr + Outp32( 0x10C00000+0x0018, 0x8080808 ); //- ctrl_offsetw + Outp32( 0x10C10000+0x0018, 0x8080808 ); //- ctrl_offsetw + Outp32( 0x10C00000+0x0028, 0x8 ); //- ctrl_offsetd[7:0]=0x8 + Outp32( 0x10C10000+0x0028, 0x8 ); //- ctrl_offsetd[7:0]=0x8 + Outp32( 0x10C00000+0x0030, 0x10100030 ); //- ctrl_force[14:8]=0x0, ctrl_start[6]=0, ctrl_dll_on[5]=1 + Outp32( 0x10C10000+0x0030, 0x10100030 ); //- ctrl_force[14:8]=0x0, ctrl_start[6]=0, ctrl_dll_on[5]=1 + DMC_Delay(100); + Outp32( 0x10C00000+0x0030, 0x10100070 ); //- ctrl_dll_start[6]=1 + Outp32( 0x10C10000+0x0030, 0x10100070 ); //- ctrl_dll_start[6]=1 + DMC_Delay(100); + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC ) != 0xC ); //- wait dfi_init_complete + Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + Outp32( 0x10DD0000+0x0000, 0x0FFF0000|(0x3<<12) ); //- dfi_init_start[28]=0, rd_fetch[14:12]=3 + Outp32( 0x10DD0000+0x00F0, 0x7 ); //- channel interleaving + Outp32( 0x10DD0000+0x0008, 0x00001333 ); //- bank interleaving + Outp32( 0x10DD0000+0x000C, 0x00001333 ); //- bank interleaving + Outp32( 0x10DD0000+0x010C, 0x00400780 ); //- chip_base[26:16]=40, chip_mask[10:0]=780 + Outp32( 0x10DD0000+0x0110, 0x00800780 ); //- chip_base[26:16]=80, chip_mask[10:0]=780 + Outp32( 0x10DD0000+0x0014, 0xFF000000 ); //- precharge policy counter + Outp32( 0x10DD0000+0x0028, 0xFFFF00FF ); //- low power counter + Outp32( 0x10DD0000+0x0030, 0x000000bb ); //- refresh counter + Outp32( 0x10DD0000+0x0034, 0x8C36650E ); //- timing row + Outp32( 0x10DD0000+0x0038, 0x3630580B ); //- timing data + Outp32( 0x10DD0000+0x003C, 0x41000A44 ); //- timing power + // Set the QOSCONTROL0~15 and BRBQOSCONFIG register if Qos Scheme is required. + Outp32( 0x10DD0000+0x60, 0xFFF ); //- QOS#0.=0xFFF + Outp32( 0x10DD0000+0x68, 0xFFF ); //- QOS#1.=0xFFF + Outp32( 0x10DD0000+0x70, 0xFFF ); //- QOS#2.=0xFFF + Outp32( 0x10DD0000+0x78, 0xFFF ); //- QOS#3.=0xFFF + Outp32( 0x10DD0000+0x80, 0xFFF ); //- QOS#4.=0xFFF + Outp32( 0x10DD0000+0x88, 0xFFF ); //- QOS#5.=0xFFF + Outp32( 0x10DD0000+0x90, 0xFFF ); //- QOS#6.=0xFFF + Outp32( 0x10DD0000+0x98, 0xFFF ); //- QOS#7.=0xFFF + Outp32( 0x10DD0000+0xA0, 0xFFF ); //- QOS#8.=0xFFF + Outp32( 0x10DD0000+0xA8, 0xFFF ); //- QOS#9.=0xFFF + Outp32( 0x10DD0000+0xB0, 0xFFF ); //- QOS#10.=0xFFF + Outp32( 0x10DD0000+0xB8, 0xFFF ); //- QOS#11.=0xFFF + Outp32( 0x10DD0000+0xC0, 0xFFF ); //- QOS#12.=0xFFF + Outp32( 0x10DD0000+0xC8, 0xFFF ); //- QOS#13.=0xFFF + Outp32( 0x10DD0000+0xD0, 0xFFF ); //- QOS#14.=0xFFF + Outp32( 0x10DD0000+0xD8, 0x0 ); //- QOS#15.=0xFFF + Outp32( 0x10DD0000+0x0010, 0x01000000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x01100000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x11000000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x11100000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x07000000 ); + Outp32( 0x10DD0000+0x0010, 0x00020000|0x18 ); + Outp32( 0x10DD0000+0x0010, 0x00030000 ); + Outp32( 0x10DD0000+0x0010, 0x00010000|dram_odt ); + Outp32( 0x10DD0000+0x0010, 0x00000000|0xD70 ); + Outp32( 0x10DD0000+0x0010, 0x0a000000 ); //- ZQInit + Outp32( 0x10DD0000+0x0010, 0x17000000 ); + Outp32( 0x10DD0000+0x0010, 0x10020000|0x18 ); + Outp32( 0x10DD0000+0x0010, 0x10030000 ); + Outp32( 0x10DD0000+0x0010, 0x10010000|dram_odt ); + Outp32( 0x10DD0000+0x0010, 0x10000000|0xD70 ); + Outp32( 0x10DD0000+0x0010, 0x1a000000 ); //- ZQInit + +#if defined(CONFIG_ODTOFF_GATELEVELINGON) + Outp32( 0x10C00000+0x0000, 386009664 ); // ctrl_atgate=1 + Outp32( 0x10C10000+0x0000, 386009664 ); // ctrl_atgate=1 + Outp32( 0x10C00000+0x0000, 386026048 ); // p0_cmd_en=1 + Outp32( 0x10C10000+0x0000, 386026048 ); // p0_cmd_en=1 + Outp32( 0x10C00000+0x0008, 65604 ); // InitDeskewEn=1 + Outp32( 0x10C10000+0x0008, 65604 ); // InitDeskewEn=1 + Outp32( 0x10C00000+0x0000, 386034240 ); // byte_rdlvl_en=1 + Outp32( 0x10C10000+0x0000, 386034240 ); // byte_rdlvl_en=1 + Outp32( 0x10C00000+0x0030, 0x10100050+0x1900 ); //- ctrl_force[14:8], ctrl_dll_on[5]=0 + Outp32( 0x10C10000+0x0030, 0x10100050+0x1900 ); //- ctrl_force[14:8], ctrl_dll_on[5]=0 + Outp32( 0x10C00000+0x0008, 16842820 ); // rdlvl_gate_en=1 + Outp32( 0x10C10000+0x0008, 16842820 ); // rdlvl_gate_en=1 + Outp32( 0x10C00000+0x0000, 386034496 ); // ctrl_shgate=1 + Outp32( 0x10C10000+0x0000, 386034496 ); // ctrl_shgate=1 + Outp32( 0x10C00000+0x0004, 0x9010100 ); // ctrl_gateduradj=0 + Outp32( 0x10C10000+0x0004, 0x9010100 ); // ctrl_gateduradj=0 + Outp32( 0x10DD0000+0x00f8, 0x00000001 ); //- ctrl_rdlvl_data_en[1]=1 + while( ( Inp32( 0x10DD0000+0x0040 ) & 0xC000 ) != 0xC000 ); //- Rdlvl_complete_ch1[15]=1, Rdlvl_complete_ch0[14]=1 + Outp32( 0x10DD0000+0x00f8, 0x00000000 ); //- ctrl_rdlvl_data_en[1]=0 + Outp32( 0x10C00000+0x0038, 0x00000000 ); //- ctrl_pulld_dq[11:8]=0x0, ctrl_pulld_dqs[3:0]=0x0 + Outp32( 0x10C10000+0x0038, 0x00000000 ); //- ctrl_pulld_dq[11:8]=0x0, ctrl_pulld_dqs[3:0]=0x0 + Outp32( 0x10C00000+0x0030, 0x10100070+0x1900 ); //- ctrl_force[14:8], ctrl_start[6]=1, ctrl_dll_on[5]=1 + Outp32( 0x10C10000+0x0030, 0x10100070+0x1900 ); //- ctrl_force[14:8], ctrl_start[6]=1, ctrl_dll_on[5]=1 + DMC_Delay(100); + Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- ctrl_shgate[29]=1, fp_resync[3]=1 + Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- ctrl_shgate[29]=1, fp_resync[3]=0 + Outp32( 0x10DD0000+0x0010, 0x01000000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x01100000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x11000000 ); //- Issue PALL + Outp32( 0x10DD0000+0x0010, 0x11100000 ); //- Issue PALL +#endif + Outp32( 0x10DD0000+0x0004, 0x00302620 ); //- bl[22:20]=8, mem_type[11:8]=7, dsref_en[5]=1, dpwrdn_en[1]=1, clk_stop_en[0]=1 + Outp32( 0x10DD0000+0x0000, 0x0FFF0020|(0x3<<12) ); //- dfi_init_start[28]=1, rd_fetch[14:12]=3, aref_en[5]=1 + + mem_ctrl_init_done(); +} diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/mem_init_ddr3.S b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/mem_init_ddr3.S new file mode 100755 index 000000000..a86b192e3 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/mem_init_ddr3.S @@ -0,0 +1,412 @@ +/* + * (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. + * + */ + +#include <Platform/ArmPlatform.h> +#include <Platform/Arndale5250.h> +#include <Platform/Exynos5250_Evt1.h> +#include <Platform/Arndale5250_Val.h> +#include <AutoGen.h> + +GCC_ASM_EXPORT(ArmPlatformSecBootMemoryInit) +GCC_ASM_EXPORT(ArmPlatformClockInitialize) +GCC_ASM_EXPORT(ArmPlatformTZPCInitialize) +GCC_ASM_EXPORT(ArmPlatformSecBootAction) + +#define MCLK_CDREX_800 1 +#define CONFIG_LOW_POWER_CTRL 1 +@#define CONFIG_DMC_BRB +#define LPDDR3PHY_CTRL_CON3 0x20A20 + +ASM_PFX(ArmPlatformSecBootMemoryInit): + @push {lr} + mov r12, lr + + @Outp32( 0x10030200, 0. ); //- rCLK_SRC_CDREX + ldr r0, =0x10030200 + ldr r1, =0 + str r1, [r0] + @Outp32( 0x10030500, 16777297. ); //- rCLK_DIV_CDREX + ldr r0, =0x10030500 + ldr r1, =16777297 + str r1, [r0] + @Outp32( 0x10014104, 2111488. ); // rMPLL_CON1 + ldr r0, =0x10014104 + ldr r1, =2111488 + str r1, [r0] + @Outp32( 0x10014100, 2160591616. ); // rMPLL_CON0 + ldr r0, =0x10014100 + ldr r1, =2182417408 + str r1, [r0] +@DMC_Delay(0x10000); // wait 300ms + bl delay100 + bl delay100 + bl delay100 + @Outp32( 0x10014204, 256. ); // + ldr r0, =0x10014204 + ldr r1, =256 + str r1, [r0] +@DMC_Delay(0x10000); // wait 300ms + bl delay100 + bl delay100 + bl delay100 + @Outp32( 0x10030A10, 0x00000000 ); //- PHY_RESET[0]=0 + ldr r0, =0x10030A10 + ldr r1, =0x00000000 + str r1, [r0] +@DMC_Delay(1ms); + bl delay + @Outp32( 0x10030A10, 0x00000001 ); //- PHY_RESET[0]=1 + ldr r0, =0x10030A10 + ldr r1, =0x00000001 + str r1, [r0] +@DMC_Delay(1ms); + bl delay + @Outp32( 0x10C00000+0x00a0, 0x000006db ); //- dds of CA = 0x3 + ldr r0, =(0x10C00000+0x00a0) + ldr r1, =0x000006db + str r1, [r0] + @Outp32( 0x10C10000+0x00a0, 0x000006db ); //- dds of CA = 0x3 + ldr r0, =(0x10C10000+0x00a0) + ldr r1, =0x000006db + str r1, [r0] + @Outp32( 0x10C00000+0x00ac, 0x0000080b ); //- ctrl_bstlen[12:8]=8, ctrl_rdlat[4:0]=11 + ldr r0, =(0x10C00000+0x00ac) + ldr r1, =0x0000080b + str r1, [r0] + @Outp32( 0x10C10000+0x00ac, 0x0000080b ); //- ctrl_bstlen[12:8]=8, ctrl_rdlat[4:0]=11 + ldr r0, =(0x10C10000+0x00ac) + ldr r1, =0x0000080b + str r1, [r0] + @Outp32( 0x10C00000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_clk_div_en[18]=1 + ldr r0, =(0x10C00000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C10000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_clk_div_en[18]=1 + ldr r0, =(0x10C10000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C00000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_mode_noterm[19]=0 + ldr r0, =(0x10C00000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C10000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_mode_noterm[19]=0 + ldr r0, =(0x10C10000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C00000+0x0040, 0xE240000|0x0306 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=1 + ldr r0, =(0x10C00000+0x0040) + ldr r1, =(0xE240000|0x0306) + str r1, [r0] + @Outp32( 0x10C10000+0x0040, 0xE240000|0x0306 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=1 + ldr r0, =(0x10C10000+0x0040) + ldr r1, =(0xE240000|0x0306) + str r1, [r0] +@DMC_Delay(1ms); + bl delay + @Outp32( 0x10C00000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=0 + ldr r0, =(0x10C00000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C10000+0x0040, 0xE240000|0x0304 ); //- zq_mode_dds[26:24], zq_mode_term[23:21], zq_manual_start[1]=0 + ldr r0, =(0x10C10000+0x0040) + ldr r1, =(0xE240000|0x0304) + str r1, [r0] + @Outp32( 0x10C00000+0x0038, 0x0000000f ); //- ctrl_pulld_dq[11:8]=0xf, ctrl_pulld_dqs[3:0]=0xf + ldr r0, =(0x10C00000+0x0038) + ldr r1, =(0x0000000f) + str r1, [r0] + @Outp32( 0x10C10000+0x0038, 0x0000000f ); //- ctrl_pulld_dq[11:8]=0xf, ctrl_pulld_dqs[3:0]=0xf + ldr r0, =(0x10C10000+0x0038) + ldr r1, =(0x0000000f) + str r1, [r0] + @Outp32( 0x10DD0000+0x0000, 0x1FFF0000|(0x3<<12.) ); //- dfi_init_start[28]=1, rd_fetch[14:12]=3 + ldr r0, =(0x10DD0000+0x0000) + ldr r1, =(0x1FFF0000|(0x3<<12)) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000008) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000000) + str r1, [r0] + @Outp32( 0x10C00000+0x0010, 0x8080808 ); //- ctrl_offsetr + ldr r0, =(0x10C00000+0x0010) + ldr r1, =(0x8080808) + str r1, [r0] + @Outp32( 0x10C10000+0x0010, 0x8080808 ); //- ctrl_offsetr + ldr r0, =(0x10C10000+0x0010) + ldr r1, =(0x8080808) + str r1, [r0] + @Outp32( 0x10C00000+0x0018, 0x8080808 ); //- ctrl_offsetw + ldr r0, =(0x10C00000+0x0018) + ldr r1, =(0x8080808) + str r1, [r0] + @Outp32( 0x10C10000+0x0018, 0x8080808 ); //- ctrl_offsetw + ldr r0, =(0x10C10000+0x0018) + ldr r1, =(0x8080808) + str r1, [r0] + @Outp32( 0x10C00000+0x0028, 0x8 ); //- ctrl_offsetd[7:0]=0x8 + ldr r0, =(0x10C00000+0x0028) + ldr r1, =(0x8) + str r1, [r0] + @Outp32( 0x10C10000+0x0028, 0x8 ); //- ctrl_offsetd[7:0]=0x8 + ldr r0, =(0x10C10000+0x0028) + ldr r1, =(0x8) + str r1, [r0] + @Outp32( 0x10C00000+0x0030, 0x10100030 ); //- ctrl_force[14:8]=0x0, ctrl_start[6]=0, ctrl_dll_on[5]=1 + ldr r0, =(0x10C00000+0x0030) + ldr r1, =(0x10100030) + str r1, [r0] + @Outp32( 0x10C10000+0x0030, 0x10100030 ); //- ctrl_force[14:8]=0x0, ctrl_start[6]=0, ctrl_dll_on[5]=1 + ldr r0, =(0x10C10000+0x0030) + ldr r1, =(0x10100030) + str r1, [r0] +@DMC_Delay(1ms); +bl delay + @Outp32( 0x10C00000+0x0030, 0x10100070 ); //- ctrl_dll_start[6]=1 + ldr r0, =(0x10C00000+0x0030) + ldr r1, =(0x10100070) + str r1, [r0] + @Outp32( 0x10C10000+0x0030, 0x10100070 ); //- ctrl_dll_start[6]=1 + ldr r0, =(0x10C10000+0x0030) + ldr r1, =(0x10100070) + str r1, [r0] +@DMC_Delay(1ms); +bl delay +@DMC_Delay(1ms); +bl delay + @Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000008) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000000) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000008 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=1 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000008) + str r1, [r0] + @Outp32( 0x10DD0000+0x0018, 0xe0000000 ); //- mem_term_en[31]=1, phy_term_en[30]=1, gate signal length[29]=1, fp_resync[3]=0 + ldr r0, =(0x10DD0000+0x0018) + ldr r1, =(0xe0000000) + str r1, [r0] + @Outp32( 0x10DD0000+0x0000, 0x0FFF0000|(0x3<<12.) ); //- dfi_init_start[28]=0, rd_fetch[14:12]=3 + ldr r0, =(0x10DD0000+0x0000) + ldr r1, =(0x0FFF0000|(0x3<<12)) + str r1, [r0] + @Outp32( 0x10DD0000+0x00F0, 0x3 ); //- channel interleaving + ldr r0, =(0x10DD0000+0x00F0) + ldr r1, =(0x3) + str r1, [r0] + @Outp32( 0x10DD0000+0x0008, 0x00001333 ); //- bank interleaving + ldr r0, =(0x10DD0000+0x0008) + ldr r1, =(0x00001333) + str r1, [r0] + @Outp32( 0x10DD0000+0x000C, 0x00001333 ); //- bank interleaving + ldr r0, =(0x10DD0000+0x000C) + ldr r1, =(0x00001333) + str r1, [r0] + @Outp32( 0x10DD0000+0x010C, 0x00400780 ); //- chip_base[26:16]=40, chip_mask[10:0]=780 + ldr r0, =(0x10DD0000+0x010C) + ldr r1, =(0x00400780) + str r1, [r0] + @Outp32( 0x10DD0000+0x0110, 0x00800780 ); //- chip_base[26:16]=80, chip_mask[10:0]=780 + ldr r0, =(0x10DD0000+0x0110) + ldr r1, =(0x00800780) + str r1, [r0] + @Outp32( 0x10DD0000+0x0014, 0xFF000000 ); //- precharge policy counter + ldr r0, =(0x10DD0000+0x0014) + ldr r1, =(0xFF000000) + str r1, [r0] + @Outp32( 0x10DD0000+0x0028, 0xFFFF00FF ); //- low power counter + ldr r0, =(0x10DD0000+0x0028) + ldr r1, =(0xFFFF00FF) + str r1, [r0] + @Outp32( 0x10DD0000+0x0030, 0x000000bb ); //- refresh counter + ldr r0, =(0x10DD0000+0x0030) + ldr r1, =(0x000000bb) + str r1, [r0] + @Outp32( 0x10DD0000+0x0034, 0x8C36650E ); //- timing row + ldr r0, =(0x10DD0000+0x0034) + ldr r1, =(0x8C36650E) + str r1, [r0] + @Outp32( 0x10DD0000+0x0038, 0x3630580B ); //- timing data + ldr r0, =(0x10DD0000+0x0038) + ldr r1, =(0x3630580B) + str r1, [r0] + @Outp32( 0x10DD0000+0x003C, 0x41000A44 ); //- timing power + ldr r0, =(0x10DD0000+0x003C) + ldr r1, =(0x41000A44) + str r1, [r0] + @Outp32( 0x10DD0000+0x0010, 0x01000000 ); //- Issue PALL + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x01000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x01100000 ); //- Issue PALL + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x01100000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x11000000 ); //- Issue PALL + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x11000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x11100000 ); //- Issue PALL + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x11100000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x07000000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x07000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x00020000|0x18 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x00020000|0x18) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x00030000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x00030000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x00010000|0x42 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x00010000|0x42) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x00000000|0xD70 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x00000000|0xD70) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x0a000000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x0a000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x17000000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x17000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x10020000|0x18 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x10020000|0x18) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x10030000 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x10030000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x10010000|0x42 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x10010000|0x42) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x10000000|0xD70 ); + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x10000000|0xD70) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0010, 0x1a000000 ); //- ZQInit + ldr r0, =(0x10DD0000+0x0010) + ldr r1, =(0x1a000000) + str r1, [r0] +@DMC_Delay(100ms); +bl delay100 + @Outp32( 0x10DD0000+0x0004, 0x00302620 ); //- bl[22:20]=8, mem_type[11:8]=7, dsref_en[5]=1, dpwrdn_en[1]=1, clk_stop_en[0]=1 + ldr r0, =(0x10DD0000+0x0004) + ldr r1, =(0x00302620) + str r1, [r0] + @Outp32( 0x10DD0000+0x0000, 0x0FFF0020|(0x3<<12.) ); //- dfi_init_start[28]=1, rd_fetch[14:12]=3, aref_en[5]=1 + ldr r0, =(0x10DD0000+0x0000) + ldr r1, =(0x0FFF0020|(0x3<<12)) + str r1, [r0] + +#if defined(CONFIG_DMC_BRB) + /* DMC BRB QoS */ + ldr r0, =DMC_CTRL_BASE + ldr r1, =0x66668666 + str r1, [r0, #DMC_BRBRSVCONFIG] + ldr r1, =0xFF + str r1, [r0, #DMC_BRBRSVCONTROL] + ldr r1, =0x1 + str r1, [r0, #DMC_BRBQOSCONFIG] +#endif + @pop {lr} + mov lr, r12 + mov pc, lr + + .globl dmc_delay +dmc_delay: + subs r0, r0, #1 + bne dmc_delay + mov pc, lr + +delay100: + mov r2, #0x10000 +delayloop100: + subs r2, r2, #1 + bne delayloop100 + mov pc, lr + +delay: + mov r2, #0x100 +delayloop: + subs r2, r2, #1 + bne delayloop + mov pc, lr + +wait_pll_lock: + ldr r1, [r0, r2] + tst r1, #(1<<29) + beq wait_pll_lock + mov pc, lr + +wait_mux_state: + add r2, r2, #0x200 +check_mux_state: + ldr r1, [r0, r2] + cmp r1, r3 + bne check_mux_state + mov pc, lr + +wait_div_state: + add r2, r2, #0x100 +check_div_state: + ldr r1, [r0, r2] + cmp r1, r3 + bne check_div_state + mov pc, lr diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/DebugAgentTimerLib/DebugAgentTimerLib.c b/SamsungPlatformPkg/ArndaleBoardPkg/Library/DebugAgentTimerLib/DebugAgentTimerLib.c new file mode 100644 index 000000000..2fd2b8353 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/DebugAgentTimerLib/DebugAgentTimerLib.c @@ -0,0 +1,78 @@ +/** @file + Template for ArmEb DebugAgentLib. + + For ARM we reserve FIQ for the Debug Agent Timer. We don't care about + laytency as we only really need the timer to run a few times a second + (how fast can some one type a ctrl-c?), but it works much better if + the interrupt we are using to break into the debugger is not being + used, and masked, by the system. + + Copyright (c) 2008 - 2010, 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 <Base.h> + +#include <Library/DebugAgentTimerLib.h> + +#include <ArmEb/ArmEb.h> + + +/** + Setup all the hardware needed for the debug agents timer. + + This function is used to set up debug enviroment. + +**/ +VOID +EFIAPI +DebugAgentTimerIntialize ( + VOID + ) +{ + // Map Timer to FIQ +} + + +/** + Set the period for the debug agent timer. Zero means disable the timer. + + @param[in] TimerPeriodMilliseconds Frequency of the debug agent timer. + +**/ +VOID +EFIAPI +DebugAgentTimerSetPeriod ( + IN UINT32 TimerPeriodMilliseconds + ) +{ + if (TimerPeriodMilliseconds == 0) { + // Disable timer and Disable FIQ + return; + } + + // Set timer period and unmask FIQ +} + + +/** + Perform End Of Interrupt for the debug agent timer. This is called in the + interrupt handler after the interrupt has been processed. + +**/ +VOID +EFIAPI +DebugAgentTimerEndOfInterrupt ( + VOID + ) +{ + // EOI Timer interrupt for FIQ +} diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/Library/DebugAgentTimerLib/DebugAgentTimerLib.inf b/SamsungPlatformPkg/ArndaleBoardPkg/Library/DebugAgentTimerLib/DebugAgentTimerLib.inf new file mode 100644 index 000000000..c4ed68600 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/Library/DebugAgentTimerLib/DebugAgentTimerLib.inf @@ -0,0 +1,37 @@ +#/** @file +# Component description file for Base PCI Cf8 Library. +# +# PCI CF8 Library that uses I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles. +# Layers on top of an I/O Library instance. +# 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. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmEbDebugAgentTimerLib + FILE_GUID = 80949BBB-68EE-4a4c-B434-D5DB5A232F0C + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugAgentTimerLib|SEC BASE DXE_CORE + + +[Sources.common] + DebugAgentTimerLib.c + + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dec + +[LibraryClasses] + IoLib diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.dsc b/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.dsc new file mode 100755 index 000000000..054c90d92 --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.dsc @@ -0,0 +1,363 @@ +# +# 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. +# +# + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = Arndale-Exynos-A15_MPCore + PLATFORM_GUID = 66a5a01d-be0a-4398-9b74-5af4a261381f + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/Arndale-Exynos + SUPPORTED_ARCHITECTURES = ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.fdf + +!include SamsungPlatformPkg/ArndaleBoardPkg/ArndaleBoardPkg.dsc.inc + +[LibraryClasses.common] + ArmLib|ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf + ArmCpuLib|ArmPkg/Drivers/ArmCpuLib/ArmCortexA15Lib/ArmCortexA15Lib.inf + ArmPlatformLib|SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardLib.inf + + # Exynos5250 ArndaleBoard Specific Libraries + SerialPortLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/SerialPortLib/SerialPortLib_Evt1.inf + TimerLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/TimerLib/TimerLib.inf + RealTimeClockLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/RealTimeClockLib/RealTimeClockLib.inf + ExynosLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.inf + EfiResetSystemLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ResetSystemLib/ResetSystemLib.inf + GdbSerialLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/GdbSerialLib/GdbSerialLib.inf + FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf + + # ARM PL390 General Interrupt Driver in Secure and Non-secure + ArmGicSecLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSecLib.inf + ArmGicLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicLib.inf + ArmSmcLib|ArmPkg/Library/ArmSmcLibNull/ArmSmcLibNull.inf + +[LibraryClasses.common.SEC] + ArmLib|ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf + + ArmPlatformSecLib|SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardSecLib.inf + +[BuildOptions] + RVCT:*_*_ARM_PLATFORM_FLAGS == --cpu Cortex-A8 --fpu=softvfp -I$(WORKSPACE)/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform + + GCC:*_*_ARM_PLATFORM_FLAGS == -march=armv7-a -I$(WORKSPACE)/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform + + XCODE:*_*_ARM_PLATFORM_FLAGS == -arch armv7 -I$(WORKSPACE)/SamsungPlatformPkg/ExynosPkg/Exynos5250/Include/Platform + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|FALSE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE + +!ifdef $(EDK2_SKIP_PEICORE) + gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec|TRUE + gArmPlatformTokenSpaceGuid.PcdSendSgiToBringUpSecondaryCores|TRUE +!endif + + ## If TRUE, Graphics Output Protocol will be installed on virtual handle created by ConsplitterDxe. + # It could be set FALSE to save size. + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE + + # Install Debugger Exception Handlers. + gArmTokenSpaceGuid.PcdDebuggerExceptionSupport|TRUE + + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics|TRUE + +[PcdsFixedAtBuild.common] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"Exynos5250 Arndale" + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString|L"0.90" + gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"ARNDALE%" + gArmTokenSpaceGuid.PcdTrustzoneSupport|FALSE + + gArmTokenSpaceGuid.PcdArmScr|0x31 + + # Stack for CPU Cores in Secure Mode + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecStackBase|0x4B000000 + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase|0x4A000000 + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0x48000000 + + # Stacks for MPCores in Monitor Mode + gArmPlatformTokenSpaceGuid.PcdCPUCoresSecMonStackBase|0x4A000000 # Top of SEC Stack for Monitor World + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecMonStackSize|0x2000 # Stack for each of the 4 CPU cores + + # Non Sec UEFI Firmware: These two PCDs must match PcdFlashFvMainBase/PcdFlashFvMainSize + gArmTokenSpaceGuid.PcdFdBaseAddress |0x40000000 # Must be equal to gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase + gArmTokenSpaceGuid.PcdFdSize|0x00200000 # Must be equal to gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize + + # System Memory (256MB) + gArmTokenSpaceGuid.PcdSystemMemoryBase|0x40000000 + gArmTokenSpaceGuid.PcdSystemMemorySize|0x50000000 + + #FDT offset + gArmTokenSpaceGuid.PcdArmLinuxFdtMaxOffset|0x9000000 + + # Size of the region used by UEFI in permanent memory (Reserved 64MB) + gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x04000000 + + # Framebuffer Base Address and size + gExynosPkgTokenSpaceGuid.PcdFrameBufferBase|0x4E000000 + gExynosPkgTokenSpaceGuid.PcdFrameBufferSize|0x02000000 + + gExynosPkgTokenSpaceGuid.PcdMpSharedArgsBase|0x4D000000 + gExynosPkgTokenSpaceGuid.PcdMpSharedArgsSize|0x100000 + + # Memory Partition : Shared memory 1MB (0x4000_0000 -- 0x4010_0000) + gExynosPkgTokenSpaceGuid.PcdSmemBaseAddress|0x40200000 + gExynosPkgTokenSpaceGuid.PcdSmemSize|0x00100000 + + # Memory Partition : EMMC DMA buffer Address and Size 1MB (0x4030_0000 -- 0x4040_0000) + gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferBase|0x40300000 + #gExynosPkgTokenSpaceGuid.PcdEmmcDMABufferSize|0x00100000 + + ## iRam Base Address and size. + gExynosPkgTokenSpaceGuid.PcdiRamBootBase|0x02020000 + gExynosPkgTokenSpaceGuid.PcdiRamBootSize|0x00040000 + + ## iRam Stack Base Address and size. + gExynosPkgTokenSpaceGuid.PcdiRamStackBase|0x02050100 + gExynosPkgTokenSpaceGuid.PcdiRamStackSize|0x00000100 + + gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000 # expressed in 100ns units, 100,000 x 100 ns = 10,000,000 ns = 10 ms + + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0x40200000 + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|0x00020000 # 128K stack + + # + # ARM Pcds + # + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000040000000 + + ## PL011 - Serial Terminal + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x12C10000 + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200 + + # + # ARM Exynos PCDS + # + gExynosPkgTokenSpaceGuid.PcdConsoleUartBase|0x12C20000 + gExynosPkgTokenSpaceGuid.PcdExynos5250Evt1|TRUE + gExynosPkgTokenSpaceGuid.PcdWinDebugUartBase|0x12C30000 + gExynosPkgTokenSpaceGuid.PcdCmuBase|0x10010000 + gExynosPkgTokenSpaceGuid.PcdPWMTimerBase|0x12DD0000 + gExynosPkgTokenSpaceGuid.PcdPmuBase|0x10040000 + + gExynosPkgTokenSpaceGuid.PcdGpioPart1Base|0x11400000 + gExynosPkgTokenSpaceGuid.PcdGpioPart2Base|0x13400000 + gExynosPkgTokenSpaceGuid.PcdGpioPart3Base|0x10D10000 + gExynosPkgTokenSpaceGuid.PcdGpioPart4Base|0x03860000 + + gExynosPkgTokenSpaceGuid.PcdSdMmcCH0Base|0x12200000 + gExynosPkgTokenSpaceGuid.PcdSdMmcBase|0x12220000 + gExynosPkgTokenSpaceGuid.PcdSysBase|0x10050000 + gExynosPkgTokenSpaceGuid.PcdFIMD1Base|0x14400000 + gExynosPkgTokenSpaceGuid.PcdDSIM1Base|0x14500000 + gExynosPkgTokenSpaceGuid.PcdGICBase|0x10500000 + gExynosPkgTokenSpaceGuid.PcdTZPCBase|0x10100000 + gExynosPkgTokenSpaceGuid.PcdRtcBase|0x101E0000 + gExynosPkgTokenSpaceGuid.PcdCryptoBase|0x10830000 + + # + # ARM PL390 General Interrupt Controller + # + gArmTokenSpaceGuid.PcdGicDistributorBase|0x10481000 + gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x10482000 + #gArmTokenSpaceGuid.PcdGicNumInterrupts|160 + + # + # ARM Architectual Timer Frequency + # + gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|60000000 + + +[PcdsPatchableInModule] + ## This PCD defines the Console output column and the default value is 25 according to UEFI spec + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|53 + + ## This PCD defines the Console output row and the default value is 80 according to UEFI spec + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|75 + + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform +# +################################################################################ +[Components.common] + + # + # SEC + # + #ArmPlatformPkg/Sec/Sec.inf + SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.inf { + <LibraryClasses> + ArmGicLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicSecLib.inf + } + + # + # PEI Phase modules + # +!ifdef $(EDK2_SKIP_PEICORE) + ArmPlatformPkg/PrePi/PeiMPCore.inf { + <LibraryClasses> + ArmLib|ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf + ArmPlatformLib|SamsungPlatformPkg/ArndaleBoardPkg/Library/ArndaleBoardLib/Exynos5250/BoardLib.inf + ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf + } +!else + ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf { + <LibraryClasses> + ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/Pei/PeiArmPlatformGlobalVariableLib.inf + } + MdeModulePkg/Core/Pei/PeiMain.inf + MdeModulePkg/Universal/PCD/Pei/Pcd.inf { + <LibraryClasses> + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.inf + SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.inf + ArmPkg/Drivers/CpuPei/CpuPei.inf + IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf + MdeModulePkg/Universal/Variable/Pei/VariablePei.inf + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf { + <LibraryClasses> + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } +!endif + + # + # DXE + # + MdeModulePkg/Core/Dxe/DxeMain.inf { + <LibraryClasses> + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf + } + + # + # Architectural Protocols + # + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf + + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + + SamsungPlatformPkg/ArndaleBoardPkg/FvbDxe/FvbDxe.inf + SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.inf + # + # ACPI Support + # + MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf + MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + + # + # Samsung specific Driver + # + SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.inf + SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.inf{ + <LibraryClasses> + ExynosLib|SamsungPlatformPkg/ExynosPkg/Exynos5250/Library/ExynosLib/ExynosLib.inf + } + + # + # Multimedia Card Interface + # + SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.inf + SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.inf + # + # FAT filesystem + GPT/MBR partitioning + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # Application + # + # + # Bds + # + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + ArmPlatformPkg/Bds/Bds.inf + + # + # VariableServicesTestNonSec + # + SamsungPlatformPkg/Apps/TestApps/VariableServicesTestNonSec/VariableServicesTestNonSec.inf + + # + # TimeServicesTest + # + SamsungPlatformPkg/Apps/TestApps/TimeServicesTest/TimeServicesTest.inf + + # + # MiscellaneousServicesTest + # + SamsungPlatformPkg/Apps/TestApps/MiscellaneousServicesTest/MiscellaneousServicesTest.inf + + # + # usb host : ehci + bus + pci_emul + mass_storage + # + SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # Graphics for Exynos + # + MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.inf + + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf { + <LibraryClasses> + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf + } + + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + SamsungPlatformPkg/Apps/Tools/fwupdate/fwupdate_5250.inf + + # + # Crypto for Exynos + # + + # + # Rng for Exynos + # diff --git a/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.fdf b/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.fdf new file mode 100755 index 000000000..29e4aa36f --- /dev/null +++ b/SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.fdf @@ -0,0 +1,397 @@ +# FLASH layout file for ARM VE. +# +# 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. +# + +################################################################################ +# +# FD Section +# The [FD] Section is made up of the definition statements and a +# description of what goes into the Flash Device Image. Each FD section +# defines one flash "device" image. A flash device image may be one of +# the following: Removable media bootable image (like a boot floppy +# image,) an Option ROM image (that would be "flashed" into an add-in +# card,) a System "Flash" image (that would be burned into a system's +# flash) or an Update ("Capsule") image that will be used to update and +# existing system flash. +# +################################################################################ + + +[FD.Arndale_EFI] +BaseAddress = 0x40000000|gArmTokenSpaceGuid.PcdFdBaseAddress +Size = 0x00294000|gArmTokenSpaceGuid.PcdFdSize +ErasePolarity = 1 +BlockSize = 0x00014000 +NumBlocks = 0x21 + +################################################################################ +# +# Following are lists of FD Region layout which correspond to the locations of different +# images within the flash device. +# +# Regions must be defined in ascending order and may not overlap. +# +# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by +# the pipe "|" character, followed by the size of the region, also in hex with the leading +# "0x" characters. Like: +# Offset|Size +# PcdOffsetCName|PcdSizeCName +# RegionType <FV, DATA, or FILE> +# +################################################################################ + +0x0000000|0x00014000 +gArmTokenSpaceGuid.PcdSecureFvBaseAddress|gArmTokenSpaceGuid.PcdSecureFvSize +FV = FVMAIN_SEC + +0x00014000|0x0026C000 +gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize +FV = FVMAIN_COMPACT + +0x00284000|0x00010000 +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize +#NV_VARIABLE_STORE +DATA = { + ## This is the EFI_FIRMWARE_VOLUME_HEADER + # ZeroVector [] + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + # FileSystemGuid: gEfiSystemNvDataFvGuid = + # { 0xFFF12B8D, 0x7696, 0x4C8B, { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }} + 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, + 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50, + # FvLength: 0x20000 + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + #Signature "_FVH" #Attributes + 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00, + #HeaderLength #CheckSum #ExtHeaderOffset #Reserved #Revision + 0x48, 0x00, 0x36, 0x09, 0x00, 0x00, 0x00, 0x02, + #Blockmap[0]: 2 Blocks * 0x10000 Bytes / Block + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + #Blockmap[1]: End + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ## This is the VARIABLE_STORE_HEADER + #Signature: gEfiVariableGuid = + # { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }} + 0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41, + 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d, + #Size: 0x10000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) - 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0xFFB8 + # This can speed up the Variable Dispatch a bit. + 0xB8, 0xFF, 0x00, 0x00, + #FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32 + 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +################################################################################ +# +# FV Section +# +# [FV] section is used to define what components or modules are placed within a flash +# device file. This section also defines order the components and modules are positioned +# within the image. The [FV] section consists of define statements, set statements and +# module statements. +# +################################################################################ + +[FV.FVMAIN_SEC] +FvAlignment = 8 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/Sec/Sec.inf + + +[FV.FVMAIN] +BlockSize = 0x40 +NumBlocks = 0 # This FV gets compressed so make it just big enough +FvAlignment = 8 # FV alignment and FV attributes setting. +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + INF MdeModulePkg/Core/Dxe/DxeMain.inf + + # + # PI DXE Drivers producing Architectural Protocols (EFI Services) + # + INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf + INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf + + # + # Multiple Console IO support + # + INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + +!ifdef $(EXYNOS5250_EVT1) + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gic400Dxe/PL390GicDxe.inf +!else + INF ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf +!endif + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/TimerDxe/TimerDxe.inf + + # + # ACPI Support + # + INF MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf + INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + + # + # Samsung specific Driver + # + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/Gpio/Gpio.inf + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/eMMCDxe/eMMCDxe.inf + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/SDHCDxe_EVT1/SDHCDxe.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + INF FatBinPkg/EnhancedFatDxe/Fat.inf + INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # USB HOST STACK + # + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/PciEmulation/PciEmulation.inf + INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # Graphics for Exynos + # + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/Drivers/DisplayDxe/DisplayDxe.inf + + INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + + INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf + INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf + + # Crypto for Exynos + # + + # + # UEFI application (Shell Embedded Boot Loader) + # + INF ShellBinPkg/UefiShell/UefiShell.inf + + # + # Bds + # + INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + INF ArmPlatformPkg/Bds/Bds.inf + + # + # Firmware Updater + # + INF SamsungPlatformPkg/Apps/Tools/fwupdate/fwupdate_5250.inf + + + # + # Boot Logo + # + FILE FREEFORM = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile) { + SECTION RAW = SamsungPlatformPkg/Logo/Logo.bmp + } + + # + # FVB + # + INF SamsungPlatformPkg/ArndaleBoardPkg/FvbDxe/FvbDxe.inf + +[FV.FVMAIN_COMPACT] +FvAlignment = 8 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + +!if $(EDK2_SKIP_PEICORE) == 1 + INF ArmPlatformPkg/PrePi/PeiMPCore.inf +!else + INF MdeModulePkg/Core/Pei/PeiMain.inf + INF ArmPlatformPkg/PrePeiCore/PrePeiCoreMPCore.inf + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/PlatformPei/PlatformPeim.inf + INF SamsungPlatformPkg/ExynosPkg/Exynos5250/MemoryInitPei/MemoryInitPeim.inf + INF ArmPkg/Drivers/CpuPei/CpuPei.inf + INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf + INF IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf + INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf + INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +!endif + + FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } + } + + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + + +############################################################################ +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section # +############################################################################ +# +#[Rule.Common.DXE_DRIVER] +# FILE DRIVER = $(NAMED_GUID) { +# DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex +# COMPRESS PI_STD { +# GUIDED { +# PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi +# UI STRING="$(MODULE_NAME)" Optional +# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) +# } +# } +# } +# +############################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED { + TE TE Align = 32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + TE TE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING ="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + TE TE $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM.TIANOCOMPRESSED] + FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.USER_DEFINED.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI |.acpi + RAW ASL |.aml + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + UI STRING ="$(MODULE_NAME)" Optional + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.UEFI_APPLICATION.BINARY] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } 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__ */ diff --git a/SamsungPlatformPkg/Include/Library/PlatformBdsLib.h b/SamsungPlatformPkg/Include/Library/PlatformBdsLib.h new file mode 100644 index 000000000..8c8c288c5 --- /dev/null +++ b/SamsungPlatformPkg/Include/Library/PlatformBdsLib.h @@ -0,0 +1,156 @@ +/** @file + Platform BDS library definition. A platform can implement + instances to support platform-specific behavior. + +Copyright (c) 2008 - 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 that 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 __PLATFORM_BDS_LIB_H_ +#define __PLATFORM_BDS_LIB_H_ + +#include <Protocol/GenericMemoryTest.h> +#include <Library/GenericBdsLib.h> + +/** + Perform the memory test base on the memory test intensive level, + and update the memory resource. + + @param Level The memory test intensive level. + + @retval EFI_STATUS Successfully test all the system memory, and update + the memory resource + +**/ +typedef +EFI_STATUS +(EFIAPI *BASEM_MEMORY_TEST)( + IN EXTENDMEM_COVERAGE_LEVEL Level + ); + +/** + This routine is called to see if there are any capsules we need to process. + If the boot mode is not UPDATE, then we do nothing. Otherwise, find the + capsule HOBS and produce firmware volumes for them via the DXE service. + Then call the dispatcher to dispatch drivers from them. Finally, check + the status of the updates. + + This function should be called by BDS in case we need to do some + sort of processing even if there is no capsule to process. We + need to do this if an earlier update went away and we need to + clear the capsule variable so on the next reset PEI does not see it and + think there is a capsule available. + + @param BootMode The current boot mode + + @retval EFI_INVALID_PARAMETER The boot mode is not correct for an update. + @retval EFI_SUCCESS There is no error when processing a capsule. + +**/ +typedef +EFI_STATUS +(EFIAPI *PROCESS_CAPSULES)( + IN EFI_BOOT_MODE BootMode + ); + +/** + Platform Bds initialization. Includes the platform firmware vendor, revision + and so crc check. + +**/ +VOID +EFIAPI +PlatformBdsInit ( + VOID + ); + +/** + The function will excute with as the platform policy, current policy + is driven by boot mode. IBV/OEM can customize this code for their specific + policy action. + + @param DriverOptionList The header of the driver option link list + @param BootOptionList The header of the boot option link list + @param ProcessCapsules A pointer to ProcessCapsules() + @param BaseMemoryTest A pointer to BaseMemoryTest() + +**/ +VOID +EFIAPI +PlatformBdsPolicyBehavior ( + IN LIST_ENTRY *DriverOptionList, + IN LIST_ENTRY *BootOptionList, + IN PROCESS_CAPSULES ProcessCapsules, + IN BASEM_MEMORY_TEST BaseMemoryTest + ); + +/** + Hook point for a user-provided function, for after a boot attempt fails. + + @param Option A pointer to Boot Option that failed to boot. + @param Status The status returned from failed boot. + @param ExitData The exit data returned from failed boot. + @param ExitDataSize The exit data size returned from failed boot. + +**/ +VOID +EFIAPI +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ); + +/** + Hook point after a boot attempt succeeds. We don't expect a boot option to + return, so the UEFI 2.0 specification defines that you will default to an + interactive mode and stop processing the BootOrder list in this case. This + is also a platform implementation, and can be customized by an IBV/OEM. + + @param Option A pointer to the Boot Option that successfully booted. + +**/ +VOID +EFIAPI +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ); + + +/** + This function locks platform flash that is not allowed to be updated during normal boot path. + The flash layout is platform specific. + + **/ +VOID +EFIAPI +PlatformBdsLockNonUpdatableFlash ( + VOID + ); + +/** + Lock the ConsoleIn device in system table. All key + presses will be ignored until the Password is typed in. The only way to + disable the password is to type it in to a ConIn device. + + @param Password The password used to lock ConIn device. + + @retval EFI_SUCCESS Lock the Console In Spliter virtual handle successfully. + @retval EFI_UNSUPPORTED Password not found. + +**/ +EFI_STATUS +EFIAPI +LockKeyboards ( + IN CHAR16 *Password + ); + +#endif diff --git a/SamsungPlatformPkg/Library/PlatformBdsLib/BdsPlatform.c b/SamsungPlatformPkg/Library/PlatformBdsLib/BdsPlatform.c new file mode 100644 index 000000000..4107f85d8 --- /dev/null +++ b/SamsungPlatformPkg/Library/PlatformBdsLib/BdsPlatform.c @@ -0,0 +1,588 @@ +/*++ + +Copyright (c) 2006 - 2009, 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. + +Module Name: + + BdsPlatform.c + +Abstract: + + This file include all platform action which can be customized + by IBV/OEM. + +--*/ + +#include "BdsPlatform.h" + +//EXYNOS_SYSTEM_CONFIGURATION mSystemConfigData; + +VOID +SetupVariableInit ( + VOID + ) +{ +#if 0 + EFI_STATUS Status; + UINTN Size; + + Size = sizeof (mSystemConfigData); + Status = gRT->GetVariable ( + L"Setup", + &gEfiUnixSystemConfigGuid, + NULL, + &Size, + (VOID *) &mSystemConfigData + ); + + if (EFI_ERROR (Status)) { + // + // SetupVariable is corrupt + // + mSystemConfigData.ConOutRow = PcdGet32 (PcdConOutColumn); + mSystemConfigData.ConOutColumn = PcdGet32 (PcdConOutRow); + + Status = gRT->SetVariable ( + L"Setup", + &gEfiUnixSystemConfigGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (mSystemConfigData), + (VOID *) &mSystemConfigData + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Failed to save Setup Variable to non-volatile storage, Status = %r\n", Status)); + } + } +#endif +} + +// +// BDS Platform Functions +// +VOID +EFIAPI +PlatformBdsInit ( + VOID + ) +/*++ + +Routine Description: + + Platform Bds init. Include the platform firmware vendor, revision + and so crc check. + +Arguments: + +Returns: + + None. + +--*/ +{ + DEBUG((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + SetupVariableInit (); + DEBUG((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); +} + +EFI_STATUS +PlatformBdsConnectConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole + ) +/*++ + +Routine Description: + + Connect the predefined platform default console device. Always try to find + and enable the vga device if have. + +Arguments: + + PlatformConsole - Predfined platform default console device array. + +Returns: + + EFI_SUCCESS - Success connect at least one ConIn and ConOut + device, there must have one ConOut device is + active vga device. + + EFI_STATUS - Return the status of + BdsLibConnectAllDefaultConsoles () + +--*/ +{ + DEBUG((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + EFI_STATUS Status; + UINTN Index; + + Index = 0; + Status = EFI_SUCCESS; + + // + // Have chance to connect the platform default console, + // the platform default console is the minimue device group + // the platform should support + // + while (PlatformConsole[Index].DevicePath != NULL) { + // + // Update the console variable with the connect type + // + if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { + BdsLibUpdateConsoleVariable (L"ConIn", PlatformConsole[Index].DevicePath, NULL); + } + + if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { + BdsLibUpdateConsoleVariable (L"ConOut", PlatformConsole[Index].DevicePath, NULL); + } + + if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { + BdsLibUpdateConsoleVariable (L"ErrOut", PlatformConsole[Index].DevicePath, NULL); + } + + DEBUG((EFI_D_ERROR, "Index: %d\n", Index)); + Index++; + } + // + // Connect the all the default console with current cosole variable + // + Status = BdsLibConnectAllDefaultConsoles (); + BdsLibConnectAllConsoles (); + DEBUG((EFI_D_ERROR, "--%a:%d (Status: %X)\n", __FUNCTION__, __LINE__, Status)); + return Status; +} + +VOID +PlatformBdsConnectSequence ( + VOID + ) +/*++ + +Routine Description: + + Connect with predeined platform connect sequence, + the OEM/IBV can customize with their own connect sequence. + +Arguments: + + None. + +Returns: + + None. + +--*/ +{ + DEBUG((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + UINTN Index; + + Index = 0; + + // + // Here we can get the customized platform connect sequence + // Notes: we can connect with new variable which record the + // last time boots connect device path sequence + // + while (gPlatformConnectSequence[Index] != NULL) { + // + // Build the platform boot option + // + BdsLibConnectDevicePath (gPlatformConnectSequence[Index]); + Index++; + } + + // + // Just use the simple policy to connect all devices + // + BdsLibConnectAll (); + DEBUG((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); +} + +VOID +PlatformBdsGetDriverOption ( + IN OUT LIST_ENTRY *BdsDriverLists + ) +/*++ + +Routine Description: + + Load the predefined driver option, OEM/IBV can customize this + to load their own drivers + +Arguments: + + BdsDriverLists - The header of the driver option link list. + +Returns: + + None. + +--*/ +{ + DEBUG((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + UINTN Index; + + Index = 0; + + // + // Here we can get the customized platform driver option + // + while (gPlatformDriverOption[Index] != NULL) { + // + // Build the platform boot option + // + BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder"); + Index++; + } + DEBUG((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); + +} + +VOID +PlatformBdsDiagnostics ( + IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, + IN BOOLEAN QuietBoot, + IN BASEM_MEMORY_TEST BaseMemoryTest + ) +/*++ + +Routine Description: + + Perform the platform diagnostic, such like test memory. OEM/IBV also + can customize this fuction to support specific platform diagnostic. + +Arguments: + + MemoryTestLevel - The memory test intensive level + + QuietBoot - Indicate if need to enable the quiet boot + + BaseMemoryTest - A pointer to BdsMemoryTest() + +Returns: + + None. + +--*/ +{ + DEBUG((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + EFI_STATUS Status; + + // + // Here we can decide if we need to show + // the diagnostics screen + // Notes: this quiet boot code should be remove + // from the graphic lib + // + if (QuietBoot) { + EnableQuietBoot (PcdGetPtr(PcdLogoFile)); + // + // Perform system diagnostic + // + Status = BaseMemoryTest (MemoryTestLevel); + if (EFI_ERROR (Status)) { + DisableQuietBoot (); + } + + DEBUG((EFI_D_ERROR, "--%a:%d (Status: %X)\n", __FUNCTION__, __LINE__, Status)); + return ; + } + // + // Perform system diagnostic + // + Status = BaseMemoryTest (MemoryTestLevel); + DEBUG((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); +} + +VOID +EFIAPI +PlatformBdsPolicyBehavior ( + IN OUT LIST_ENTRY *DriverOptionList, + IN OUT LIST_ENTRY *BootOptionList, + IN PROCESS_CAPSULES ProcessCapsules, + IN BASEM_MEMORY_TEST BaseMemoryTest + ) +/*++ + +Routine Description: + + The function will excute with as the platform policy, current policy + is driven by boot mode. IBV/OEM can customize this code for their specific + policy action. + +Arguments: + + DriverOptionList - The header of the driver option link list + + BootOptionList - The header of the boot option link list + + ProcessCapsules - A pointer to ProcessCapsules() + + BaseMemoryTest - A pointer to BaseMemoryTest() + +Returns: + + None. + +--*/ +{ + DEBUG((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + EFI_STATUS Status; + UINT16 Timeout; + EFI_BOOT_MODE BootMode; + + // + // Init the time out value + // + Timeout = 5;//PcdGet16 (PcdPlatformBootTimeOut); + + // + // Load the driver option as the driver option list + // + PlatformBdsGetDriverOption (DriverOptionList); + + // + // Get current Boot Mode + // + Status = BdsLibGetBootMode (&BootMode); + + // + // Go the different platform policy with different boot mode + // Notes: this part code can be change with the table policy + // + switch (BootMode) { + + case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES: + case BOOT_WITH_MINIMAL_CONFIGURATION: + // + // In no-configuration boot mode, we can connect the + // console directly. + // + BdsLibConnectAllDefaultConsoles (); + PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); + + // + // Perform some platform specific connect sequence + // + PlatformBdsConnectSequence (); + + // + // Notes: current time out = 0 can not enter the + // front page + // + PlatformBdsEnterFrontPage (Timeout, FALSE); + + // + // Check the boot option with the boot option list + // + BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); + break; + + case BOOT_ON_FLASH_UPDATE: + // + // Boot with the specific configuration + // + PlatformBdsConnectConsole (gPlatformConsole); + PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest); + BdsLibConnectAll (); + ProcessCapsules (BOOT_ON_FLASH_UPDATE); + break; + + case BOOT_IN_RECOVERY_MODE: + // + // In recovery mode, just connect platform console + // and show up the front page + // + PlatformBdsConnectConsole (gPlatformConsole); + PlatformBdsDiagnostics (EXTENSIVE, FALSE, BaseMemoryTest); + + // + // In recovery boot mode, we still enter to the + // frong page now + // + PlatformBdsEnterFrontPage (Timeout, FALSE); + break; + + case BOOT_WITH_FULL_CONFIGURATION: + case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS: + case BOOT_WITH_DEFAULT_SETTINGS: + default: + // + // Connect platform console + // + Status = PlatformBdsConnectConsole (gPlatformConsole); + if (EFI_ERROR (Status)) { + // + // Here OEM/IBV can customize with defined action + // + PlatformBdsNoConsoleAction (); + } + + PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); + + // + // Perform some platform specific connect sequence + // + PlatformBdsConnectSequence (); + + // + // Give one chance to enter the setup if we + // have the time out + // + PlatformBdsEnterFrontPage (Timeout, FALSE); + + // + // Here we have enough time to do the enumeration of boot device + // + BdsLibEnumerateAllBootOption (BootOptionList); + break; + } + + DEBUG((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); + return ; + +} + +VOID +EFIAPI +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ) +/*++ + +Routine Description: + + Hook point after a boot attempt succeeds. We don't expect a boot option to + return, so the EFI 1.0 specification defines that you will default to an + interactive mode and stop processing the BootOrder list in this case. This + is alos a platform implementation and can be customized by IBV/OEM. + +Arguments: + + Option - Pointer to Boot Option that succeeded to boot. + +Returns: + + None. + +--*/ +{ + DEBUG((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + CHAR16 *TmpStr; + + // + // If Boot returned with EFI_SUCCESS and there is not in the boot device + // select loop then we need to pop up a UI and wait for user input. + // + TmpStr = Option->StatusString; + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); + FreePool (TmpStr); + } + DEBUG((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); +} + +VOID +EFIAPI +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ) +/*++ + +Routine Description: + + Hook point after a boot attempt fails. + +Arguments: + + Option - Pointer to Boot Option that failed to boot. + + Status - Status returned from failed boot. + + ExitData - Exit data returned from failed boot. + + ExitDataSize - Exit data size returned from failed boot. + +Returns: + + None. + +--*/ +{ + DEBUG((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + CHAR16 *TmpStr; + + // + // If Boot returned with failed status then we need to pop up a UI and wait + // for user input. + // + TmpStr = Option->StatusString; + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); + FreePool (TmpStr); + } + DEBUG((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); +} + +EFI_STATUS +PlatformBdsNoConsoleAction ( + VOID + ) +/*++ + +Routine Description: + + This function is remained for IBV/OEM to do some platform action, + if there no console device can be connected. + +Arguments: + + None. + +Returns: + + EFI_SUCCESS - Direct return success now. + +--*/ +{ + DEBUG((EFI_D_ERROR, "++%a:%d\n", __FUNCTION__, __LINE__)); + DEBUG((EFI_D_ERROR, "--%a:%d\n", __FUNCTION__, __LINE__)); + return EFI_SUCCESS; +} + +VOID +EFIAPI +PlatformBdsLockNonUpdatableFlash ( + VOID + ) +{ + return; +} + +/** + Lock the ConsoleIn device in system table. All key + presses will be ignored until the Password is typed in. The only way to + disable the password is to type it in to a ConIn device. + + @param Password Password used to lock ConIn device. + + @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully. + @retval EFI_UNSUPPORTED Password not found + +**/ +EFI_STATUS +EFIAPI +LockKeyboards ( + IN CHAR16 *Password + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/SamsungPlatformPkg/Library/PlatformBdsLib/BdsPlatform.h b/SamsungPlatformPkg/Library/PlatformBdsLib/BdsPlatform.h new file mode 100644 index 000000000..41aa4459f --- /dev/null +++ b/SamsungPlatformPkg/Library/PlatformBdsLib/BdsPlatform.h @@ -0,0 +1,130 @@ +/*++ + +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. + +Module Name: + + BdsPlatform.h + +Abstract: + + Head file for BDS Platform specific code + +--*/ + +#ifndef _BDS_PLATFORM_H +#define _BDS_PLATFORM_H + +#include <PiDxe.h> + +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseLib.h> +#include <Library/PcdLib.h> +#include <Library/GenericBdsLib.h> +#include <Library/PlatformBdsLib.h> +#include <Library/DevicePathLib.h> + +//#include <Protocol/ExynosThunk.h> +//#include <Protocol/ExynosIo.h> +//#include <Guid/ExynosSystemConfig.h> + +extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[]; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[]; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[]; + + +#pragma pack(1) +typedef struct { + // + // Console output mode + // + UINT32 ConOutColumn; + UINT32 ConOutRow; +} EXYNOS_SYSTEM_CONFIGURATION; +#pragma pack() + + +#define gEndEntire \ + { \ + END_DEVICE_PATH_TYPE,\ + END_ENTIRE_DEVICE_PATH_SUBTYPE,\ + END_DEVICE_PATH_LENGTH,\ + 0\ + } + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + UINT32 Instance; +} EXYNOS_VENDOR_DEVICE_PATH_NODE; + +// +// Below is the platform console device path +// + +typedef struct { + VENDOR_DEVICE_PATH ExynosBus; + EFI_DEVICE_PATH_PROTOCOL End; +} EXYNOS_GOP_DEVICE_PATH; + +typedef struct { + VENDOR_DEVICE_PATH ExynosBus; + EFI_DEVICE_PATH_PROTOCOL End; +} EXYNOS_CONSOLE_DEVICE_PATH; +// +// Platform BDS Functions +// +VOID +PlatformBdsGetDriverOption ( + IN LIST_ENTRY *BdsDriverLists + ) +; + +EFI_STATUS +BdsMemoryTest ( + EXTENDMEM_COVERAGE_LEVEL Level + ) +; + + +VOID +PlatformBdsConnectSequence ( + VOID + ) +; + +EFI_STATUS +ProcessCapsules ( + EFI_BOOT_MODE BootMode + ) +; + +EFI_STATUS +PlatformBdsConnectConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole + ) +; + +EFI_STATUS +PlatformBdsNoConsoleAction ( + VOID + ) +; + +VOID +PlatformBdsEnterFrontPage ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ); + +#endif // _BDS_PLATFORM_H diff --git a/SamsungPlatformPkg/Library/PlatformBdsLib/PlatformBdsLib.inf b/SamsungPlatformPkg/Library/PlatformBdsLib/PlatformBdsLib.inf new file mode 100644 index 000000000..93aacbe52 --- /dev/null +++ b/SamsungPlatformPkg/Library/PlatformBdsLib/PlatformBdsLib.inf @@ -0,0 +1,63 @@ +## @file +# Platfrom BDS driver +# +# Do platform action customized by IBV/OEM. +# 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 = PlatformBdsLib + FILE_GUID = f392b762-8985-11db-be87-0040d02b1835 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + BdsPlatform.c + PlatformData.c + BdsPlatform.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseMemoryLib + DebugLib + PcdLib + GenericBdsLib + DevicePathLib + + +[Guids] + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile + +[Depex] + gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid diff --git a/SamsungPlatformPkg/Library/PlatformBdsLib/PlatformData.c b/SamsungPlatformPkg/Library/PlatformBdsLib/PlatformData.c new file mode 100644 index 000000000..76c31f3ba --- /dev/null +++ b/SamsungPlatformPkg/Library/PlatformBdsLib/PlatformData.c @@ -0,0 +1,88 @@ +/*++ + +Copyright (c) 2006 - 2009, 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. + +Module Name: + + PlatformData.c + +Abstract: + + Defined the platform specific device path which will be used by + platform Bbd to perform the platform policy connect. + +--*/ + +#include "BdsPlatform.h" +#include <Protocol/SerialIo.h> +#include <Protocol/GraphicsOutput.h> + + +// +// Predefined platform default time out value +// +UINT16 gPlatformBootTimeOutDefault = 10; + +// +// Platform specific keyboard device path +// +EXYNOS_GOP_DEVICE_PATH gGopDevicePath = { + { // ExynosBus + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + }, + EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID + }, + gEndEntire +}; + +EXYNOS_CONSOLE_DEVICE_PATH gConsoleDevicePath = { + { // ExynosBus + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + }, + EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID + }, + gEndEntire +}; + +// +// Predefined platform default console device path +// +BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = { + { + (EFI_DEVICE_PATH_PROTOCOL *) &gConsoleDevicePath, + (CONSOLE_OUT | CONSOLE_IN) + }, + { + (EFI_DEVICE_PATH_PROTOCOL *) &gGopDevicePath, + (CONSOLE_OUT | CONSOLE_IN) + }, + { + NULL, + 0 + } +}; + +// +// Predefined platform specific driver option +// +EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL }; + +// +// Predefined platform connect sequence +// +EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL }; diff --git a/SamsungPlatformPkg/Logo/Logo.bmp b/SamsungPlatformPkg/Logo/Logo.bmp Binary files differnew file mode 100755 index 000000000..f4db08e4d --- /dev/null +++ b/SamsungPlatformPkg/Logo/Logo.bmp diff --git a/SamsungPlatformPkg/README b/SamsungPlatformPkg/README new file mode 100644 index 000000000..a4973c260 --- /dev/null +++ b/SamsungPlatformPkg/README @@ -0,0 +1,48 @@ + +=== ArndaleBoard OVERVIEW === + +The project aims to support UEFI for Exynos 5250 Soc using the edk2 +code base. + +=== STATUS === + +Current capabilities: +* Uefi Boot from microSD card + +=== FUTURE PLANS === + +* Support for PXE, SATA, ACPI, USB + - KeyBoard, Mouse and MassStorage + +=== BUILDING ARNDALE Board === + +Pre-requisites: +* Build environment capable of build the edk2 MdeModulePkg. +* A properly configured ASL compiler: + - Intel ASL compiler: Available from http://www.acpica.org + - Microsoft ASL compiler: Available from http://www.acpi.info + +Getting bl1: +Download the bl1 from https://wiki.linaro.org/Boards/Arndale/Setup/EnterpriseUbuntuServer?action=AttachFile&do=view&target=arndale-bl1.img + +Build the ArndaleBoardPkg by running from the Workspace +build -p SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.dsc -a ARM -t ARMGCC -b RELEASE -D EXYNOS5250_EVT1 -D DDR3 for release version + +Following the edk2 build process, you will find the Arndale binaries +under the $WORKSPACE/Build/*/*/FV directory. You can find the below +mentioned binary image. +* ARNDALE_EFI.FD + +=== RUNNING ArndaleBoardPkg on the Arndale board === +* need to be in Linux Environment to do the below procedure +* Insert the microSD card. +* copy the arndale-bl1.img to the SD/MMC card by using the comand + sudo dd if=arndale-bl1.img of=/dev/sdX bs=512 seek=1 +* Copy the Uefi Image to SD/MMC with below command from the Workspace. + sudo dd if=Build/ArndaleBoard-Exynos/RELEASE_ARMGCC/FV/ARNDALE_EFI.fd of=/dev/sdX bs=512 seek=49 +* Now the booting device is ready to be used. +* Insert the SDMMC card in the Arndale board reader slot MMC Ch2. +* Connect the Uart cable from the Arndale device to the PC terminal. +* Power ON the Device. +* The boot message should be visible on the termial. +* Finally, it should give boot options. diff --git a/SamsungPlatformPkg/SamsungPlatformPkg.dec b/SamsungPlatformPkg/SamsungPlatformPkg.dec new file mode 100644 index 000000000..32c21f4c2 --- /dev/null +++ b/SamsungPlatformPkg/SamsungPlatformPkg.dec @@ -0,0 +1,42 @@ +#/** @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 = SamsungPlatformPkg + 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] + +[Guids.common] + +[PcdsFeatureFlag.common] + +[PcdsFixedAtBuild.common] + +[Protocols.common] + gSamsungPlatformGpioProtocolGuid = { 0x82b4b2f7, 0x8c18, 0x4dbe, { 0xb7, 0x2e, 0x6a, 0x59, 0xd4, 0x23, 0x0c, 0x40 }} + gSamsungPlatformI2CProtocolGuid = { 0x3e71c1f9, 0xe5e4, 0x482b, { 0xac, 0x1e, 0x50, 0xf5, 0x43, 0x59, 0xc8, 0x65 }} + gSamsungPlatformRngProtocolGuid = { 0xcdfc7301, 0x38a3, 0x4b4b, { 0xb4, 0x57, 0x8a, 0x72, 0x38, 0xfb, 0xed, 0xf7 }} diff --git a/SamsungPlatformPkg/build.sh b/SamsungPlatformPkg/build.sh new file mode 100755 index 000000000..cd2e59c59 --- /dev/null +++ b/SamsungPlatformPkg/build.sh @@ -0,0 +1,126 @@ +#!/bin/bash +unset ARCH +unset ARMLINUXGCC_TOOLS_PATH +unset EDK_TOOLS_PATH +unset WORKSPACE + +if [ "$1" = "help" ] +then + echo "" + echo "USAGE:" + echo " ./build help : shows this message" + echo " ./build : build with BaseTools, GccShellPkg" + echo " ./build init : build with BaseTools Only" + echo " ./build shell : build with GccShellPkg Only" + echo " ./build arndale : build with SamsungPlatformPkg for Arndale" + echo "" + exit +fi + +export ARMLINUXGCC_TOOLS_PATH=/usr/local/arm/bin/ +export EDK_TOOLS_PATH=`pwd`/BaseTools +. ./edksetup.sh BaseTools + +DEFINE_CMD= + +for arg in "$@"; do + args="${args} ${arg}" +done + +DEFINE_CMD=$args + + + +if [ "$1" = "arndale" ] +then + DEFINE_CMD=" -D EXYNOS5250_EVT1 -D DDR3" +else + DEFINE_CMD= +fi + +echo " Parameter is ["$DEFINE_CMD"]" +if [ "$1" = "init" ] +then + if [ ! -d BaseTools/Source/C/bin ] + then + cd ./BaseTools + make clean + cd ../ + make -C ./BaseTools + else + echo "Already build BaseTools....." + echo "" + fi + +elif [ "$1" = "shell" ] +then + if [ -d GccShellPkg ] + then + build -p GccShellPkg/GccShellPkg.dsc -a ARM -t ARMLINUXGCC -b DEBUG + if [ -f Build/GccShellPkg/DEBUG_ARMLINUXGCC/ARM/ShellFull.efi ] + then + cp Build/GccShellPkg/DEBUG_ARMLINUXGCC/ARM/ShellFull.efi EdkShellBinPkg/FullShell/ARM/Shell_Full.efi + echo "To copy ShellFull.efi to EdkShellBinPkg/FullShell/ARM is done......" + echo "" + fi + else + echo "" + echo "Not found Directory : ---------> GccShellPkg !!!!" + echo "" + exit + fi + +elif [ "$1" = "arndale" ] +then + if [ ! -d BaseTools/Source/C/bin ] + then + cd ./BaseTools + make clean + cd ../ + make -C ./BaseTools + else + echo "Already build BaseTools....." + echo "" + fi + + if [ -d SamsungPlatformPkg ] + then + build -p SamsungPlatformPkg/ArndaleBoardPkg/arndale-Exynos5250.dsc -a ARM -t ARMLINUXGCC -b DEBUG $DEFINE_CMD + echo "ARNDALE_EFI.fd can be found in path Build/Arndale-Exynos/DEBUG_ARMLINUXGCC/FV/" + else + echo "" + echo "Not found Directory : ---------> SamsungPlatformPkg !!!!" + echo "" + exit + fi + +else + # Build BaseTools + if [ ! -d BaseTools/Source/C/bin ] + then + cd ./BaseTools + make clean + cd ../ + make -C ./BaseTools + else + echo "Already build BaseTools....." + echo "" + fi + + # Build GccShellPkg + if [ -d GccShellPkg ] + then + build -p GccShellPkg/GccShellPkg.dsc -a ARM -t ARMLINUXGCC -b DEBUG + if [ -f Build/GccShellPkg/DEBUG_ARMLINUXGCC/ARM/ShellFull.efi ] + then + cp Build/GccShellPkg/DEBUG_ARMLINUXGCC/ARM/ShellFull.efi EdkShellBinPkg/FullShell/ARM/Shell_Full.efi + echo "To copy ShellFull.efi to EdkShellBinPkg/FullShell/ARM is done......" + echo "" + fi + else + echo "" + echo "Not found Directory : ---------> GccShellPkg !!!!" + echo "" + fi + +fi diff --git a/SamsungPlatformPkg/patches/0001-The-patch-created-to-incorporate-auto-boot-feature.patch b/SamsungPlatformPkg/patches/0001-The-patch-created-to-incorporate-auto-boot-feature.patch new file mode 100644 index 000000000..91aea9603 --- /dev/null +++ b/SamsungPlatformPkg/patches/0001-The-patch-created-to-incorporate-auto-boot-feature.patch @@ -0,0 +1,150 @@ +From 011bc2be4b3f2a5a5413511d7380b6fe3632d0f5 Mon Sep 17 00:00:00 2001 +From: Shivamurthy Shastri <shiva.murthy@samsung.com> +Date: Wed, 5 Dec 2012 14:44:57 +0530 +Subject: [PATCH] The patch created to incorporate auto boot feature for + arndale board. + +Signed-off-by: Shivamurthy Shastri <shiva.murthy@samsung.com> +--- + ArmPlatformPkg/Bds/BootOption.c | 71 ++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 67 insertions(+), 4 deletions(-) + +diff --git a/ArmPlatformPkg/Bds/BootOption.c b/ArmPlatformPkg/Bds/BootOption.c +index 289d36a..468050d 100644 +--- a/ArmPlatformPkg/Bds/BootOption.c ++++ b/ArmPlatformPkg/Bds/BootOption.c +@@ -14,6 +14,11 @@ + + #include "BdsInternal.h" + ++#include <Library/DxeServicesTableLib.h> ++#include <Protocol/BlockIo.h> ++#include <Guid/DebugImageInfoTable.h> ++#include <Protocol/DevicePathToText.h> ++ + extern EFI_HANDLE mImageHandle; + + EFI_STATUS +@@ -22,26 +27,61 @@ BootOptionStart ( + ) + { + EFI_STATUS Status; +- EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; ++ //EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; + UINT32 LoaderType; + ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; + ARM_BDS_LINUX_ARGUMENTS* LinuxArguments; + EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath; +- EFI_DEVICE_PATH_PROTOCOL* DefaultFdtDevicePath; +- UINTN FdtDevicePathSize; ++ //EFI_DEVICE_PATH_PROTOCOL* DefaultFdtDevicePath; ++ //UINTN FdtDevicePathSize; + UINTN CmdLineSize; + UINTN InitrdSize; + EFI_DEVICE_PATH* Initrd; + UINT16 LoadOptionIndexSize; + ++ UINTN HandleCount; ++ EFI_HANDLE *HandleBuffer; ++ UINTN Index; ++ //CHAR16* String; ++ //EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol; ++ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; ++ EFI_DEVICE_PATH_PROTOCOL *LoadImageDevicePath; ++ EFI_DEVICE_PATH_PROTOCOL *FileSystemDevicePath; ++ + if (IS_ARM_BDS_BOOTENTRY (BootOption)) { + Status = EFI_UNSUPPORTED; + OptionalData = BootOption->OptionalData; + LoaderType = ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType); + ++ BdsConnectAllDrivers(); ++ ++ Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); ++ if (EFI_ERROR (Status)) { ++ AsciiPrint ("Did not find the DevicePathToTextProtocol.\n"); ++ return Status; ++ } ++ ++ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &HandleBuffer); ++ if (EFI_ERROR (Status)) { ++ AsciiPrint ("No device path found\n"); ++ return Status; ++ } ++ ++ /*for (Index = 0; Index < HandleCount; Index++) { ++ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol); ++ String = DevicePathToTextProtocol->ConvertDevicePathToText(DevicePathProtocol,TRUE,TRUE); ++ Print (L"[0x%X] %s\n",(UINT32)HandleBuffer[Index], String); ++ }*/ ++ ++ for (Index = 0; Index < HandleCount; Index++) { ++ //Get the device path ++ FileSystemDevicePath = DevicePathFromHandle(HandleBuffer[Index]); ++ if (FileSystemDevicePath == NULL) { ++ continue; ++ } ++ + if (LoaderType == BDS_LOADER_EFI_APPLICATION) { + // Need to connect every drivers to ensure no dependencies are missing for the application +- BdsConnectAllDrivers(); + + Status = BdsStartEfiApplication (mImageHandle, BootOption->FilePathList, 0, NULL); + } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) { +@@ -55,9 +95,18 @@ BootOptionStart ( + Initrd = NULL; + } + ++ //Check if zImage file on SD-MMC. ++ LoadImageDevicePath = FileDevicePath(HandleBuffer[Index], L"uImage"); ++ Status = BdsBootLinuxAtag (LoadImageDevicePath, Initrd, (CHAR8*)(LinuxArguments + 1)); ++ if (EFI_ERROR(Status)) { ++ continue; ++ } ++ ++#if 0 + Status = BdsBootLinuxAtag (BootOption->FilePathList, + Initrd, // Initrd + (CHAR8*)(LinuxArguments + 1)); // CmdLine ++#endif + } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) { + LinuxArguments = &(OptionalData->Arguments.LinuxArguments); + CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); +@@ -69,6 +118,7 @@ BootOptionStart ( + Initrd = NULL; + } + ++#if 0 + // Get the default FDT device path + Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); + ASSERT_EFI_ERROR(Status); +@@ -78,13 +128,26 @@ BootOptionStart ( + FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath); + Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath); + ASSERT_EFI_ERROR(Status); ++#endif ++ ++ //Check if zImage file on SD-MMC. ++ LoadImageDevicePath = FileDevicePath(HandleBuffer[Index], L"uImage"); ++ FdtDevicePath = FileDevicePath(HandleBuffer[Index], L"exynos5250-arndale.dtb"); ++ Status = BdsBootLinuxFdt (LoadImageDevicePath, Initrd, (CHAR8*)(LinuxArguments + 1), FdtDevicePath); ++ FreePool (FdtDevicePath); ++ if (EFI_ERROR(Status)) { ++ continue; ++ } ++ } + ++#if 0 + Status = BdsBootLinuxFdt (BootOption->FilePathList, + Initrd, // Initrd + (CHAR8*)(LinuxArguments + 1), + FdtDevicePath); + + FreePool (FdtDevicePath); ++#endif + } + } else { + // Set BootCurrent variable +-- +1.8.0 + |