summaryrefslogtreecommitdiff
path: root/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c')
-rw-r--r--Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c
new file mode 100644
index 0000000000..678b5a0082
--- /dev/null
+++ b/Silicon/Hisilicon/Library/I2CLib/I2CLibRuntime.c
@@ -0,0 +1,109 @@
+/** @file
+*
+* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
+* Copyright (c) 2015, Linaro 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 <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/PlatformSysCtrlLib.h>
+#include "I2CLibInternal.h"
+
+STATIC EFI_EVENT mI2cLibVirtualAddrChangeEvent;
+
+STATIC UINTN gI2cBase[MAX_SOCKET][I2C_PORT_MAX];
+
+UINTN GetI2cBase (UINT32 Socket, UINT8 Port)
+{
+ if (gI2cBase[Socket][Port] == 0) {
+ gI2cBase[Socket][Port] = PlatformGetI2cBase(Socket, Port);
+ }
+
+ return gI2cBase[Socket][Port];
+}
+
+VOID
+EFIAPI
+I2cLibVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINT32 Socket;
+ UINT8 Port;
+
+ // We assume that all I2C ports used in one runtime driver need to be
+ // converted into virtual address.
+ for (Socket = 0; Socket < MAX_SOCKET; Socket++) {
+ for (Port = 0; Port < I2C_PORT_MAX; Port++) {
+ if (gI2cBase[Socket][Port] != 0) {
+ EfiConvertPointer (0x0, (VOID **)&gI2cBase[Socket][Port]);
+ }
+ }
+ }
+
+ return;
+}
+
+EFI_STATUS
+I2cLibRuntimeSetup (UINT32 Socket, UINT8 Port)
+{
+ EFI_STATUS Status;
+
+ UINTN Base = GetI2cBase (Socket, Port);
+
+ // Declare the controller as EFI_MEMORY_RUNTIME
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ Base, SIZE_64KB,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_WARN, "[%a:%d] AddMemorySpace failed: %r\n", __FUNCTION__, __LINE__, Status));
+ }
+
+ Status = gDS->SetMemorySpaceAttributes (Base, SIZE_64KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] SetMemorySpaceAttributes failed: %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+
+ //
+ // Register for the virtual address change event
+ //
+ // Only create event once
+ if (mI2cLibVirtualAddrChangeEvent == NULL) {
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ I2cLibVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mI2cLibVirtualAddrChangeEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[%a:%d] Create event failed: %r\n", __FUNCTION__, __LINE__, Status));
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+