1d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm/** @file
2d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*
3d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*  Copyright (c) 2011, ARM Limited. All rights reserved.
4d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*
5d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*  This program and the accompanying materials
6d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*  are licensed and made available under the terms and conditions of the BSD License
7d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*  which accompanies this distribution.  The full text of the license may be found at
8d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*  http://opensource.org/licenses/bsd-license.php
9d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*
10d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm*
13d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm**/
14d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
15d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <Uefi.h>
16d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
17d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <Library/BaseMemoryLib.h>
18d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <Library/UefiBootServicesTableLib.h>
19d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <Library/UefiRuntimeServicesTableLib.h>
20d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <Library/DebugLib.h>
21d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <Library/IoLib.h>
22d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
23d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <Protocol/RealTimeClock.h>
24d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <Protocol/EmbeddedExternalDevice.h>
25d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
26d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <Omap3530/Omap3530.h>
27d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm#include <TPS65950.h>
28d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
29d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
30d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEMBEDDED_EXTERNAL_DEVICE   *gTPS65950;
31d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmINT16                      TimeZone = EFI_UNSPECIFIED_TIMEZONE;
32d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
33d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm/**
34d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Returns the current time and date information, and the time-keeping capabilities
35d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  of the hardware platform.
36d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
37d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  Time                  A pointer to storage to receive a snapshot of the current time.
38d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  Capabilities          An optional pointer to a buffer to receive the real time clock
39d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm                                device's capabilities.
40d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
41d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_SUCCESS           The operation completed successfully.
42d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_INVALID_PARAMETER Time is NULL.
43d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_DEVICE_ERROR      The time could not be retrieved due to hardware error.
44d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
45d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm**/
46d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFI_STATUS
47d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFIAPI
48d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmLibGetTime (
49d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  OUT EFI_TIME                *Time,
50d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  OUT EFI_TIME_CAPABILITIES   *Capabilities
51d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  )
52d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm{
53d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  EFI_STATUS            Status;
54d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  UINT8                 Data;
55d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  EFI_TPL               OldTpl;
56d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
57d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Time == NULL) {
58d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    return EFI_INVALID_PARAMETER;
59d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  }
60d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
61d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
62d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
63d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  /* Get time and date */
64d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  ZeroMem(Time, sizeof(EFI_TIME));
65d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
66d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  // Latch values
67d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, RTC_CTRL_REG), 1, &Data);
68d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
69d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Data |= BIT6;
70d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, RTC_CTRL_REG), 1, &Data);
71d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
72d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
73d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  // Read registers
74d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, YEARS_REG), 1, &Data);
75d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
76d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Time->Year = 2000 + ((Data >> 4) & 0xF) * 10 + (Data & 0xF);
77d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
78d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, MONTHS_REG), 1, &Data);
79d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
80d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Time->Month = ((Data >> 4) & 0x1) * 10 + (Data & 0xF);
81d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
82d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, DAYS_REG), 1, &Data);
83d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
84d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Time->Day = ((Data >> 4) & 0x3) * 10 + (Data & 0xF);
85d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
86d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, HOURS_REG), 1, &Data);
87d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
88d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Time->Hour = ((Data >> 4) & 0x3) * 10 + (Data & 0xF);
89d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
90d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, MINUTES_REG), 1, &Data);
91d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
92d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Time->Minute = ((Data >> 4) & 0x7) * 10 + (Data & 0xF);
93d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
94d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, SECONDS_REG), 1, &Data);
95d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
96d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Time->Second = ((Data >> 4) & 0x7) * 10 + (Data & 0xF);
97d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
98d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Time->TimeZone = TimeZone;
99d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  // TODO: check what to use here
100d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;
101d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
102d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  // Set capabilities
103d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
104d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  // TODO: Set real capabilities
105d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Capabilities != NULL) {
106d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    Capabilities->Resolution = 1;
107d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    Capabilities->Accuracy = 50000000;
108d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    Capabilities->SetsToZero = FALSE;
109d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  }
110d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
111d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEXIT:
112d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  gBS->RestoreTPL(OldTpl);
113d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
114d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  return (Status == EFI_SUCCESS) ? Status : EFI_DEVICE_ERROR;
115d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm}
116d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
117d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm/**
118d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Sets the current local time and date information.
119d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
120d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  Time                  A pointer to the current time.
121d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
122d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_SUCCESS           The operation completed successfully.
123d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_INVALID_PARAMETER A time field is out of range.
124d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_DEVICE_ERROR      The time could not be set due due to hardware error.
125d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
126d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm**/
127d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFI_STATUS
128d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFIAPI
129d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmLibSetTime (
130d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  IN EFI_TIME                *Time
131d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  )
132d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm{
133d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  EFI_STATUS Status;
134d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  UINT8      Data;
135d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  UINT8      MonthDayCount[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
136d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  EFI_TPL    OldTpl;
137d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
138d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  // Input validation according both to UEFI spec and hardware constraints
139d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  // UEFI spec says valid year range is 1900-9999 but TPS only supports 2000-2099
140d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if ( (Time == NULL)
141d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    || (Time->Year < 2000 || Time->Year > 2099)
142d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    || (Time->Month < 1 || Time->Month > 12)
143d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    || (Time->Day < 1 || Time->Day > MonthDayCount[Time->Month])
144d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    || (Time->Hour > 23)
145d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    || (Time->Minute > 59)
146d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    || (Time->Second > 59)
147d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    || (Time->Nanosecond > 999999999)
148d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    || ((Time->TimeZone < -1440 || Time->TimeZone > 1440) && Time->TimeZone != 2047)
149d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  ) {
150d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm    return EFI_INVALID_PARAMETER;
151d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  }
152d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
153d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
154d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
155d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Data = Time->Year - 2000;
156d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, YEARS_REG), 1, &Data);
157d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
158d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
159d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Data = ((Time->Month / 10) << 4) | (Time->Month % 10);
160d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, MONTHS_REG), 1, &Data);
161d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
162d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
163d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Data = ((Time->Day / 10) << 4) | (Time->Day % 10);
164d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, DAYS_REG), 1, &Data);
165d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
166d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
167d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Data = ((Time->Hour / 10) << 4) | (Time->Hour % 10);
168d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, HOURS_REG), 1, &Data);
169d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
170d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
171d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Data = ((Time->Minute / 10) << 4) | (Time->Minute % 10);
172d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, MINUTES_REG), 1, &Data);
173d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
174d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
175d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Data = ((Time->Second / 10) << 4) | (Time->Second % 10);
176d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, SECONDS_REG), 1, &Data);
177d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  if (Status != EFI_SUCCESS) goto EXIT;
178d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
179d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  TimeZone = Time->TimeZone;
180d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
181d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEXIT:
182d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  gBS->RestoreTPL(OldTpl);
183d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
184d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  return (Status == EFI_SUCCESS) ? Status : EFI_DEVICE_ERROR;
185d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm}
186d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
187d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm/**
188d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Returns the current wakeup alarm clock setting.
189d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
190d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  Enabled               Indicates if the alarm is currently enabled or disabled.
191d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  Pending               Indicates if the alarm signal is pending and requires acknowledgement.
192d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  Time                  The current alarm setting.
193d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
194d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_SUCCESS           The alarm settings were returned.
195d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_INVALID_PARAMETER Any parameter is NULL.
196d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_DEVICE_ERROR      The wakeup time could not be retrieved due to a hardware error.
197d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
198d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm**/
199d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFI_STATUS
200d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFIAPI
201d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmLibGetWakeupTime (
202d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  OUT BOOLEAN     *Enabled,
203d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  OUT BOOLEAN     *Pending,
204d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  OUT EFI_TIME    *Time
205d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  )
206d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm{
207d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  return EFI_UNSUPPORTED;
208d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm}
209d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
210d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm/**
211d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Sets the system wakeup alarm clock time.
212d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
213d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  Enabled               Enable or disable the wakeup alarm.
214d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  Time                  If Enable is TRUE, the time to set the wakeup alarm for.
215d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
216d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_SUCCESS           If Enable is TRUE, then the wakeup alarm was enabled. If
217d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm                                Enable is FALSE, then the wakeup alarm was disabled.
218d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_INVALID_PARAMETER A time field is out of range.
219d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_DEVICE_ERROR      The wakeup time could not be set due to a hardware error.
220d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
221d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
222d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm**/
223d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFI_STATUS
224d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFIAPI
225d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmLibSetWakeupTime (
226d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  IN BOOLEAN      Enabled,
227d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  OUT EFI_TIME    *Time
228d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  )
229d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm{
230d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  return EFI_UNSUPPORTED;
231d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm}
232d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
233d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm/**
234d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  This is the declaration of an EFI image entry point. This can be the entry point to an application
235d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  written to this specification, an EFI boot service driver, or an EFI runtime driver.
236d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
237d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  ImageHandle           Handle that identifies the loaded image.
238d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param  SystemTable           System Table for this image.
239d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
240d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @retval EFI_SUCCESS           The operation completed successfully.
241d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
242d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm**/
243d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFI_STATUS
244d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFIAPI
245d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmLibRtcInitialize (
246d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  IN EFI_HANDLE                            ImageHandle,
247d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  IN EFI_SYSTEM_TABLE                      *SystemTable
248d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  )
249d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm{
250d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  EFI_STATUS    Status;
251d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  EFI_HANDLE    Handle;
252d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  UINT8         Data;
253d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  EFI_TPL       OldTpl;
254d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
255d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
256d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  ASSERT_EFI_ERROR(Status);
257d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
258d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  OldTpl = gBS->RaiseTPL(TPL_NOTIFY);
259d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Data = 1;
260d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, RTC_CTRL_REG), 1, &Data);
261d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  ASSERT_EFI_ERROR(Status);
262d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  gBS->RestoreTPL(OldTpl);
263d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
264d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  // Setup the setters and getters
265d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  gRT->GetTime       = LibGetTime;
266d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  gRT->SetTime       = LibSetTime;
267d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  gRT->GetWakeupTime = LibGetWakeupTime;
268d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  gRT->SetWakeupTime = LibSetWakeupTime;
269d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
270d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  // Install the protocol
271d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Handle = NULL;
272d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Status = gBS->InstallMultipleProtocolInterfaces (
273d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm                  &Handle,
274d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm                  &gEfiRealTimeClockArchProtocolGuid,  NULL,
275d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm                  NULL
276d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm                 );
277d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
278d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  return Status;
279d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm}
280d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
281d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm/**
282d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Fixup internal data so that EFI can be call in virtual mode.
283d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  Call the passed in Child Notify event and convert any pointers in
284d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  lib to virtual mode.
285d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm
286d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param[in]    Event   The Event that is being processed
287d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  @param[in]    Context Event Context
288d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm**/
289d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmVOID
290d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmEFIAPI
291d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif LindholmLibRtcVirtualNotifyEvent (
292d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  IN EFI_EVENT        Event,
293d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  IN VOID             *Context
294d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  )
295d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm{
296d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm  return;
297d6d2a59a443ba5ba5ba75fbbd176ed9a051d2db0Leif Lindholm}
298