mirror of https://github.com/acidanthera/audk.git
292 lines
9.3 KiB
C
292 lines
9.3 KiB
C
/** @file
|
|
*
|
|
* Copyright (c) 2011, ARM Limited. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
*
|
|
**/
|
|
|
|
#include <Uefi.h>
|
|
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/IoLib.h>
|
|
|
|
#include <Protocol/RealTimeClock.h>
|
|
#include <Protocol/EmbeddedExternalDevice.h>
|
|
|
|
#include <Omap3530/Omap3530.h>
|
|
#include <TPS65950.h>
|
|
|
|
|
|
EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
|
|
INT16 TimeZone = EFI_UNSPECIFIED_TIMEZONE;
|
|
|
|
/**
|
|
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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 Data;
|
|
EFI_TPL OldTpl;
|
|
|
|
if (Time == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
|
|
|
|
/* Get time and date */
|
|
ZeroMem(Time, sizeof(EFI_TIME));
|
|
|
|
// Latch values
|
|
Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, RTC_CTRL_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
Data |= BIT6;
|
|
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, RTC_CTRL_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
|
|
// Read registers
|
|
Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, YEARS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
Time->Year = 2000 + ((Data >> 4) & 0xF) * 10 + (Data & 0xF);
|
|
|
|
Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, MONTHS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
Time->Month = ((Data >> 4) & 0x1) * 10 + (Data & 0xF);
|
|
|
|
Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, DAYS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
Time->Day = ((Data >> 4) & 0x3) * 10 + (Data & 0xF);
|
|
|
|
Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, HOURS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
Time->Hour = ((Data >> 4) & 0x3) * 10 + (Data & 0xF);
|
|
|
|
Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, MINUTES_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
Time->Minute = ((Data >> 4) & 0x7) * 10 + (Data & 0xF);
|
|
|
|
Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, SECONDS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
Time->Second = ((Data >> 4) & 0x7) * 10 + (Data & 0xF);
|
|
|
|
Time->TimeZone = TimeZone;
|
|
// TODO: check what to use here
|
|
Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;
|
|
|
|
// Set capabilities
|
|
|
|
// TODO: Set real capabilities
|
|
if (Capabilities != NULL) {
|
|
Capabilities->Resolution = 1;
|
|
Capabilities->Accuracy = 50000000;
|
|
Capabilities->SetsToZero = FALSE;
|
|
}
|
|
|
|
EXIT:
|
|
gBS->RestoreTPL(OldTpl);
|
|
|
|
return (Status == EFI_SUCCESS) ? Status : 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
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 Data;
|
|
UINT8 MonthDayCount[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
|
EFI_TPL OldTpl;
|
|
|
|
// Input validation according both to UEFI spec and hardware constraints
|
|
// UEFI spec says valid year range is 1900-9999 but TPS only supports 2000-2099
|
|
if ( (Time == NULL)
|
|
|| (Time->Year < 2000 || Time->Year > 2099)
|
|
|| (Time->Month < 1 || Time->Month > 12)
|
|
|| (Time->Day < 1 || Time->Day > MonthDayCount[Time->Month])
|
|
|| (Time->Hour > 23)
|
|
|| (Time->Minute > 59)
|
|
|| (Time->Second > 59)
|
|
|| (Time->Nanosecond > 999999999)
|
|
|| ((Time->TimeZone < -1440 || Time->TimeZone > 1440) && Time->TimeZone != 2047)
|
|
) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
|
|
|
|
Data = Time->Year - 2000;
|
|
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, YEARS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
|
|
Data = ((Time->Month / 10) << 4) | (Time->Month % 10);
|
|
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, MONTHS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
|
|
Data = ((Time->Day / 10) << 4) | (Time->Day % 10);
|
|
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, DAYS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
|
|
Data = ((Time->Hour / 10) << 4) | (Time->Hour % 10);
|
|
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, HOURS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
|
|
Data = ((Time->Minute / 10) << 4) | (Time->Minute % 10);
|
|
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, MINUTES_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
|
|
Data = ((Time->Second / 10) << 4) | (Time->Second % 10);
|
|
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, SECONDS_REG), 1, &Data);
|
|
if (Status != EFI_SUCCESS) goto EXIT;
|
|
|
|
TimeZone = Time->TimeZone;
|
|
|
|
EXIT:
|
|
gBS->RestoreTPL(OldTpl);
|
|
|
|
return (Status == EFI_SUCCESS) ? Status : 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
|
|
)
|
|
{
|
|
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
|
|
)
|
|
{
|
|
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_STATUS Status;
|
|
EFI_HANDLE Handle;
|
|
UINT8 Data;
|
|
EFI_TPL OldTpl;
|
|
|
|
Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
|
|
ASSERT_EFI_ERROR(Status);
|
|
|
|
OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
|
|
Data = 1;
|
|
Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, RTC_CTRL_REG), 1, &Data);
|
|
ASSERT_EFI_ERROR(Status);
|
|
gBS->RestoreTPL(OldTpl);
|
|
|
|
// Setup the setters and getters
|
|
gRT->GetTime = LibGetTime;
|
|
gRT->SetTime = LibSetTime;
|
|
gRT->GetWakeupTime = LibGetWakeupTime;
|
|
gRT->SetWakeupTime = LibSetWakeupTime;
|
|
|
|
// Install the protocol
|
|
Handle = NULL;
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Handle,
|
|
&gEfiRealTimeClockArchProtocolGuid, NULL,
|
|
NULL
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
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
|
|
)
|
|
{
|
|
return;
|
|
}
|