/** @file | |
FDT client library for ARM's PL031 RTC driver | |
Copyright (c) 2016, Linaro 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. | |
**/ | |
#include <Uefi.h> | |
#include <Library/BaseLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/PcdLib.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Protocol/FdtClient.h> | |
RETURN_STATUS | |
EFIAPI | |
ArmVirtPL031FdtClientLibConstructor ( | |
VOID | |
) | |
{ | |
EFI_STATUS Status; | |
FDT_CLIENT_PROTOCOL *FdtClient; | |
INT32 Node; | |
CONST UINT64 *Reg; | |
UINT32 RegSize; | |
UINT64 RegBase; | |
RETURN_STATUS PcdStatus; | |
Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, | |
(VOID **)&FdtClient); | |
ASSERT_EFI_ERROR (Status); | |
Status = FdtClient->FindCompatibleNode (FdtClient, "arm,pl031", &Node); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((EFI_D_WARN, "%a: No 'arm,pl031' compatible DT node found\n", | |
__FUNCTION__)); | |
return EFI_SUCCESS; | |
} | |
Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", | |
(CONST VOID **)&Reg, &RegSize); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((EFI_D_WARN, | |
"%a: No 'reg' property found in 'arm,pl031' compatible DT node\n", | |
__FUNCTION__)); | |
return EFI_SUCCESS; | |
} | |
ASSERT (RegSize == 16); | |
RegBase = SwapBytes64 (Reg[0]); | |
ASSERT (RegBase < MAX_UINT32); | |
PcdStatus = PcdSet32S (PcdPL031RtcBase, (UINT32)RegBase); | |
ASSERT_RETURN_ERROR (PcdStatus); | |
DEBUG ((EFI_D_INFO, "Found PL031 RTC @ 0x%Lx\n", RegBase)); | |
// | |
// UEFI takes ownership of the RTC hardware, and exposes its functionality | |
// through the UEFI Runtime Services GetTime, SetTime, etc. This means we | |
// need to disable it in the device tree to prevent the OS from attaching | |
// its device driver as well. | |
// | |
Status = FdtClient->SetNodeProperty (FdtClient, Node, "status", | |
"disabled", sizeof ("disabled")); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((EFI_D_WARN, "Failed to set PL031 status to 'disabled'\n")); | |
} | |
return EFI_SUCCESS; | |
} |