From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM11-CO1-obe.outbound.protection.outlook.com (NAM11-CO1-obe.outbound.protection.outlook.com [40.107.220.131]) by mx.groups.io with SMTP id smtpd.web09.9814.1637167791799452754 for ; Wed, 17 Nov 2021 08:49:52 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@os.amperecomputing.com header.s=selector2 header.b=d0dqBdKY; spf=pass (domain: os.amperecomputing.com, ip: 40.107.220.131, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OZSN1zquIzu9JYLtuVEKruYr2S6VgLc2hXhx+jqgl/zWH7DguQAUQw5cDcSX0ZvKs8gLazC0mcMpX2etoiZX7Ru15/xz9DWLxabFykWS341qFea7xFT2XmdFl5n6tewmU/Y84V31sT3zVwNJcmr0g5Wji7zzJOlmpoiMCIq/0ngi8JHYTqzY46/rFWDV34LIYPucxkTVPJo6Appe6Up/8yh1B05KuMFyGQ+IMFAkysPt4tjt6JcojRU7HrMlkEqIWCGYrijIMNTpJldPB8J7Lxh7ECDW+wj0Ubs0Ri9ZD5V3B/LRmkw2zWGRr+w4rSxcZzkyjjqe1+eJr6HDlKpXGQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=V/xYWFdL5NDSeyBiKD0zFOdNH/umbz4g6JXvKlcQWfQ=; b=AJlCGpLxfd6j7qDT3sNu4Uw09g3bHVzU56auKV5pahKTEDISVNBAPebxFhsE9BytKDg+SvsmcwI59fyaleKCup5spCHVSKQ86yg8rbVY8kn6525OpweDIjzcHIjVBEA87iyFYk37z9nlIplXWIQyqDEvXNaHaa3Q1n3B5+o4XmNmkknkd3jNARsxU1uQfyI9IcTNYAIgij39p6hfTGQQq5EYazZ5yuWA4fd62IJJJdAT2cM6QD41CFaNre3Aca/SjZU3xIZbMZyLSDbvx/NjiKh1l8i/GaPfTYCrUoHkSRzZYPPAUtKlal6HPDAuQDCtSbIFxRAHMmiO7o8TGoOiVA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=os.amperecomputing.com; dkim=pass header.d=os.amperecomputing.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=os.amperecomputing.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=V/xYWFdL5NDSeyBiKD0zFOdNH/umbz4g6JXvKlcQWfQ=; b=d0dqBdKYWvGoUUX8+U7TtpQbaQxP1nYlh9+xLV3b8jdh7r9dcHAzuX//y/F7fRyV1LKWa90WbLHb1eSvghHKnq5SAZAKmY0Ea6soxMYSATmQJ3cyvdkIhh9lvfjh3vJmoncSsSRYehtfC/OlxKzvLqreMfdeLggorSdQBggc1QE= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=os.amperecomputing.com; Received: from PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) by PH0PR01MB6454.prod.exchangelabs.com (2603:10b6:510:1b::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.20; Wed, 17 Nov 2021 16:49:50 +0000 Received: from PH0PR01MB7287.prod.exchangelabs.com ([fe80::254c:9533:7f35:aee]) by PH0PR01MB7287.prod.exchangelabs.com ([fe80::254c:9533:7f35:aee%4]) with mapi id 15.20.4713.019; Wed, 17 Nov 2021 16:49:50 +0000 From: "Nhi Pham" To: devel@edk2.groups.io CC: patches@amperecomputing.com, nhi@os.amperecomputing.com, vunguyen@os.amperecomputing.com, Thang Nguyen , Chuong Tran , Phong Vo , Leif Lindholm , Michael D Kinney , Ard Biesheuvel , Nate DeSimone Subject: [edk2-platforms][PATCH v5 05/30] JadePkg: Implement RealTimeClockLib for PCF85063 Date: Wed, 17 Nov 2021 23:47:02 +0700 Message-ID: <20211117164727.10922-6-nhi@os.amperecomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211117164727.10922-1-nhi@os.amperecomputing.com> References: <20211117164727.10922-1-nhi@os.amperecomputing.com> X-ClientProxiedBy: HKAPR04CA0001.apcprd04.prod.outlook.com (2603:1096:203:d0::11) To PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 Received: from sw004.amperecomputing.com (118.69.219.201) by HKAPR04CA0001.apcprd04.prod.outlook.com (2603:1096:203:d0::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.21 via Frontend Transport; Wed, 17 Nov 2021 16:49:47 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 2955fc48-1375-4d34-e020-08d9a9ea453d X-MS-TrafficTypeDiagnostic: PH0PR01MB6454: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:901; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: uqbmT99RCENpNEdfAC94O2vPK1d/1OWa3Rl3hW166IiAY+Lz9oQQwC4/Nw/KDwk4rugMC1RcP2Wmr+e3aaS56ICZj6hlQlQ1XDg82fDc40AAicSiK8hCSZNLqh35/E7w5Ch1BOh8Oo8loH7VaFWWo6qFynUJZkWJrgCvEkfLYunKyyzxC5c8f3SP3ArBvbEMa6DCvIoRReytHSLH0xPWHQijBw5T/sqCgUxEOUBeH7bhkR+5sxAW7xVxYdj0Xipq4ArbEzxVVzK8I0s/AiBReNdrTrOYw1kOtBlpzlv/h/D3W485bgoADZJ2Uwmp+4Y7SG5nOgn9OigPBOip2jOlE24oUkMSQASgeYPg7cfPNvfiZmBdnyW8DQS1UOau+Lh7d5XtzlLEXWgrAYEbLpTybQyYSsnm8bSFC5kgIe4/ijfDTiuprFl+J1PXa+fFRm0Ap5mI4bvJG2HsBkLe6CN654Lkuc2Ds4Q8TuwquWsTfCIvOyu8MGjyxBXvC3OdK03juUqHDTcPLjAXl4NIgIoCoQ6vBxvTX78bc092BJGbzE+NUANsaFRfLvGVQMgWKKxde4ITpiu/igA1pjctxguzpY0TAViKjnDKdwkap78rKMip/xKsEdvbBjmiJ5PKb1e0k9MupN4nK94NJK//R/2Ag21SihmFW+Vl7JLEzTQf3VtumbaIGdQI8kwa5M5Srs/jqVRD5WA3HPgDoA+BxNQu5A== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH0PR01MB7287.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(6666004)(8936002)(66476007)(52116002)(186003)(86362001)(2906002)(1076003)(83380400001)(54906003)(4326008)(66556008)(26005)(38100700002)(38350700002)(19627235002)(30864003)(6506007)(6916009)(6486002)(2616005)(956004)(5660300002)(6512007)(316002)(8676002)(66946007)(508600001);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?e5njw5MoxztSZwIOZWLyMr7UXOm4r9PpL9AcozWfdsFy+xX25WzX+D8zOY58?= =?us-ascii?Q?RiljuIDpgh6jQP+bgfoUKZ3KWE4FLjYjv8eRAoxC1XrOakp9LOG6RCEab6lq?= =?us-ascii?Q?nCvs0vV0+mnL6wp6yVZrLxLw7OvxVTFYmXTdYoI1q2HSN5Ks/RbpZTJa5k+J?= =?us-ascii?Q?I4kCJoC5FQJVzx1y+i6R+3Zynnn5VFQn3Hn7B1B8N1prj4tzSgwmq+4T54/P?= =?us-ascii?Q?zUuzLkyPk81RlJk+9iKONqTAuUt3AEGz7nTqVjg12CVnY/BumCBi+ob8aqZU?= =?us-ascii?Q?FyMHmkzm98DPJwKrK3K6iPAWtaT9Aie9sW0+QAQJk3QK1uesR+eE+mGSF+os?= =?us-ascii?Q?Ag/M3YnLWHzhIUg6miam2u7vkRCt+Vdu7BTV1vr77VQJ9PveL0JEokeIN7SL?= =?us-ascii?Q?CXAVTETgqFeEcsOWBOV+hiQr4uTXf3FyF+sv3jJDizXwhqtjx/0/snNnptOw?= =?us-ascii?Q?6D7jzIDV8TIB3vdFQNJySur1nkV37dvPKtQJHQWyhIYc5ZA+FdnyO1ofLm/m?= =?us-ascii?Q?48NDNyRLqnAaqcZN8ZJtYj08S4khx7Tlz2MDXmZs031Eh0qpg/RnqSNzq1mi?= =?us-ascii?Q?zbzfJerb9Ts6LBTmg0sUImT3O0JAC40xbBY9i4dYjSy37rUxAs9U+xyMnV8f?= =?us-ascii?Q?inU11auPstNLvExEJeve2nCvmX69ruprHcyrt1gFTTdOHVvxn6qOJPVe8RrV?= =?us-ascii?Q?QOnWOUSgrvmNusgWseZtG+Asry+u2n94AaHExTtYMWA3wuDpXrOYdUbfusTH?= =?us-ascii?Q?pdRvjhOd1a3UWKb3cuF1TRidIa8EgOSoe3TMiJqVhscKMmA9K0wU5MfO3vKV?= =?us-ascii?Q?6styGTY94yvPnbonwi+KV+zCY9bH1ajLRv1wN3oTVmc9QTHPbwgYWrvQby8t?= =?us-ascii?Q?YXGODWrEHs06dgp6/0srbf7770QdWDOqC1YclChxvHkGdNv2e0kuW5t+Jue0?= =?us-ascii?Q?lbJGFdvCPWPYsGYxwQFfhIgKPUIaFAwyZX7Jl461yHu9fctTuYB/VnlBtYgv?= =?us-ascii?Q?PEZYXk6up86zJp8c52rogHBrzWv9Q3L/dSUVD9x7F3lqpgFTV32NnSQCao9o?= =?us-ascii?Q?tmqcgHfCmrvOzXlWys0f9ioo/J7b+JGU2aBJg9zhSeW34s4s2nQ2uEtmBEiz?= =?us-ascii?Q?B8ZsrhLbX5KfnbtXn8/6SSuYqZP0yUm4qcldbv1RvvXPRWTzD2MAjkcymm1+?= =?us-ascii?Q?7wEctI5hIZRYLY6jpKFaxtNXHtMzb9ThZ5KXkquA8dot5P1XYIXt+YzWIeil?= =?us-ascii?Q?d5tjgQnp7kzubCWP+hjPT+bwTxqGrzkV9Ij7t8i3wQP6hEG5HWl1eYz7u7GO?= =?us-ascii?Q?GjhTpC4O0cTc/RFGspBPTYb2oGRrLmEjRWTrVX2OjEpZHMRjqPTaPiQakVP3?= =?us-ascii?Q?rMJINBemIiGXQkzTaf0HRS2ZsHcbjhl3uQFHpcA309HYgxlgNcnu7hkn+A53?= =?us-ascii?Q?yZRI9RC3+Lq/ljz3jhczMly1YT/kZh/Nd8TELTTX5bYamVnuRZDB1O8LEA73?= =?us-ascii?Q?8aoX+FvwrzQLD61NAlFJ3Cmg10P22ANKNZEmimZ1GUaqxEuqMsFSI3gcj8cG?= =?us-ascii?Q?aVRC0C51D92BQFmOSDZVEHLGKgcehz3+n/ux6cbeVxHjM/FLfRMDPb1EAtuo?= =?us-ascii?Q?ypLklGxQZK1+sEKJVJ2Auv0HCOt/1QlBbujJPflnk4J3W7h1IoZPdwR5dUp+?= =?us-ascii?Q?fb4Anw=3D=3D?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2955fc48-1375-4d34-e020-08d9a9ea453d X-MS-Exchange-CrossTenant-AuthSource: PH0PR01MB7287.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Nov 2021 16:49:50.2822 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: g93e/CU6bKkvLBRPdDj6XFxynzkPRbyUh59aepelzInLsNEUBBD1+JRK/lG3zaVPsYDFUdqTpBS3d6tpzi9SoZRZ0v8Mwt5tk6yZBY5CEx4= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB6454 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain This library adds the support for retrieving and updating system datetime over real RTC PCF85063 device on Mt. Jade platform instead of using virtual RTC. Cc: Thang Nguyen Cc: Chuong Tran Cc: Phong Vo Cc: Leif Lindholm Cc: Michael D Kinney Cc: Ard Biesheuvel Cc: Nate DeSimone Signed-off-by: Nhi Pham Reviewed-by: Leif Lindholm --- Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc = | 2 + Platform/Ampere/JadePkg/Jade.dsc = | 2 +- Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeC= lockLib.inf | 44 +++ Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h = | 91 ++++++ Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c = | 317 ++++++++++++++++++++ Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeC= lockLib.c | 257 ++++++++++++++++ 6 files changed, 712 insertions(+), 1 deletion(-) diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon= /Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc index cf1be4df8f27..326bdfb5ced5 100644 --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc @@ -83,6 +83,8 @@ [LibraryClasses.common] SystemFirmwareInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/SystemF= irmwareInterfaceLib/SystemFirmwareInterfaceLib.inf AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCp= uLib.inf TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf + I2cLib|Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.inf + GpioLib|Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.inf MmCommunicationLib|Silicon/Ampere/AmpereAltraPkg/Library/MmCommunication= Lib/MmCommunicationLib.inf FlashLib|Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf =20 diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jad= e.dsc index a10591933cf7..7b70c5d6b5fb 100644 --- a/Platform/Ampere/JadePkg/Jade.dsc +++ b/Platform/Ampere/JadePkg/Jade.dsc @@ -74,7 +74,7 @@ [LibraryClasses] # # RTC Library: Common RTC # - RealTimeClockLib|EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualReal= TimeClockLib.inf + RealTimeClockLib|Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLi= b/PCF85063RealTimeClockLib.inf =20 ##########################################################################= ###### # diff --git a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85= 063RealTimeClockLib.inf b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeC= lockLib/PCF85063RealTimeClockLib.inf new file mode 100644 index 000000000000..1fe561cc0ec9 --- /dev/null +++ b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063Real= TimeClockLib.inf @@ -0,0 +1,44 @@ +## @file +# +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001B + MODULE_TYPE =3D BASE + BASE_NAME =3D PCF85063RealTimeClockLib + FILE_GUID =3D 271569F6-5522-4006-9FF5-F07A59473AA= C + LIBRARY_CLASS =3D RealTimeClockLib + VERSION_STRING =3D 1.0 + +[Sources.common] + PCF85063.c + PCF85063.h + PCF85063RealTimeClockLib.c + +[Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec + Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec + +[LibraryClasses] + ArmGenericTimerCounterLib + ArmLib + BaseLib + DebugLib + GpioLib + DxeServicesTableLib + I2cLib + TimeBaseLib + TimerLib + UefiLib + UefiRuntimeLib + +[Guids] + gEfiEventVirtualAddressChangeGuid diff --git a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85= 063.h b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h new file mode 100644 index 000000000000..03ce4d29a03f --- /dev/null +++ b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h @@ -0,0 +1,91 @@ +/** @file + + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef PCF85063_H_ +#define PCF85063_H_ + +#include + +#include +#include + +// +// I2C bus address that RTC connected to +// +#define I2C_RTC_BUS_ADDRESS 1 + +// +// I2C RTC bus speed +// +#define I2C_RTC_BUS_SPEED 100000 + +// +// I2C chip address that RTC connected to +// +#define I2C_RTC_CHIP_ADDRESS 0x51 + +// +// The GPI PIN that tell if RTC can be access +// +#define I2C_RTC_ACCESS_GPIO_PIN 28 + +/** + * Returns the current time and date information of the hardware platform. + * + * @param Time A pointer to storage to receive a snapsho= t of the current time. + * + * + * @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 ha= rdware error. + */ +EFI_STATUS +EFIAPI +PlatformGetTime ( + OUT EFI_TIME *Time + ); + +/** + * Set the time and date information to the hardware platform. + * + * @param Time A pointer to storage to set the current t= ime to hardware platform. + * + * + * @retval EFI_SUCCESS The operation completed successfully. + * @retval EFI_INVALID_PARAMETER Time is NULL. + * @retval EFI_DEVICE_ERROR The time could not be set due due to hard= ware error. + **/ +EFI_STATUS +EFIAPI +PlatformSetTime ( + IN EFI_TIME *Time + ); + +/** + * Callback function for hardware platform to convert data pointers to vir= tual address + */ +VOID +EFIAPI +PlatformVirtualAddressChangeEvent ( + VOID + ); + +/** + * Callback function for hardware platform to initialize private data + * + * + * @retval EFI_SUCCESS The operation completed successfully. + * @retval Others The error status indicates the error + */ +EFI_STATUS +EFIAPI +PlatformInitialize ( + VOID + ); + +#endif /* PCF85063_H_ */ diff --git a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85= 063.c b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c new file mode 100644 index 000000000000..bc886b530f3c --- /dev/null +++ b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c @@ -0,0 +1,317 @@ +/** @file + + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PCF85063.h" + +#define RTC_TIMEOUT_WAIT_ACCESS 100000 /* 100 miliseconds */ +#define RTC_DEFAULT_MIN_YEAR 2000 +#define RTC_DEFAULT_MAX_YEAR 2099 + +#define RTC_ADDR 0x4 +#define RTC_DATA_BUF_LEN 8 + +/** + * PCF85063 register offsets + */ +#define PCF85063_OFFSET_SEC 0x0 +#define PCF85063_OFFSET_MIN 0x1 +#define PCF85063_OFFSET_HR 0x2 +#define PCF85063_OFFSET_DAY 0x3 +#define PCF85063_OFFSET_WKD 0x4 +#define PCF85063_OFFSET_MON 0x5 +#define PCF85063_OFFSET_YEA 0x6 + +/** + * PCF85063 encoding macros + */ +#define PCF85063_SEC_ENC(s) (((((s) / 10) & 0x7) << 4) | (((s) % 10) & 0xf= )) +#define PCF85063_MIN_ENC(m) (((((m) / 10) & 0x7) << 4) | (((m) % 10) & 0xf= )) +#define PCF85063_HR_ENC(h) (((((h) / 10) & 0x3) << 4) | (((h) % 10) & 0xf= )) +#define PCF85063_DAY_ENC(d) (((((d) / 10) & 0x3) << 4) | (((d) % 10) & 0xf= )) +#define PCF85063_WKD_ENC(w) ((w) & 0x7) +#define PCF85063_MON_ENC(m) (((((m) / 10) & 0x1) << 4) | (((m) % 10) & 0xf= )) +#define PCF85063_YEA_ENC(y) (((((y) / 10) & 0xf) << 4) | (((y) % 10) & 0xf= )) + +/** + * PCF85063 decoding macros + */ +#define PCF85063_SEC_DEC(s) (((((s) & 0x70) >> 4) * 10) + ((s) & 0xf)) +#define PCF85063_MIN_DEC(m) (((((m) & 0x70) >> 4) * 10) + ((m) & 0xf)) +#define PCF85063_HR_DEC(h) (((((h) & 0x30) >> 4) * 10) + ((h) & 0xf)) +#define PCF85063_DAY_DEC(d) (((((d) & 0x30) >> 4) * 10) + ((d) & 0xf)) +#define PCF85063_WKD_DEC(w) ((w) & 0x7) +#define PCF85063_MON_DEC(m) (((((m) & 0x10) >> 4) * 10) + ((m) & 0xf)) +#define PCF85063_YEA_DEC(y) (((((y) & 0xf0) >> 4) * 10) + ((y) & 0xf)) + +/* Buffer pointers to convert Vir2Phys and Phy2Vir */ +STATIC volatile UINT64 RtcBufVir; +STATIC volatile UINT64 RtcBufPhy; + +STATIC +EFI_STATUS +RtcI2cWaitAccess ( + VOID + ) +{ + INTN Timeout; + + Timeout =3D RTC_TIMEOUT_WAIT_ACCESS; + while ((GpioReadBit (I2C_RTC_ACCESS_GPIO_PIN) !=3D 0) && (Timeout > 0)) = { + MicroSecondDelay (100); + Timeout -=3D 100; + } + + if (Timeout <=3D 0) { + DEBUG ((DEBUG_ERROR, "%a: Timeout while waiting access RTC\n", __FUNCT= ION__)); + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +RtcI2cRead ( + IN UINT8 Addr, + IN OUT UINT64 Data, + IN UINT32 DataLen + ) +{ + EFI_STATUS Status; + UINT32 TmpLen; + + if (EFI_ERROR (RtcI2cWaitAccess ())) { + return EFI_DEVICE_ERROR; + } + + Status =3D I2cProbe (I2C_RTC_BUS_ADDRESS, I2C_RTC_BUS_SPEED); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Send the slave address for read + // + TmpLen =3D 1; + Status =3D I2cWrite (I2C_RTC_BUS_ADDRESS, I2C_RTC_CHIP_ADDRESS, (UINT8 *= )&Addr, &TmpLen); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Read back the time + // + Status =3D I2cRead (I2C_RTC_BUS_ADDRESS, I2C_RTC_CHIP_ADDRESS, NULL, 0, = (UINT8 *)Data, &DataLen); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +RtcI2cWrite ( + IN UINT8 Addr, + IN UINT64 Data, + IN UINT32 DataLen + ) +{ + EFI_STATUS Status; + UINT8 TmpBuf[RTC_DATA_BUF_LEN + 1]; + UINT32 TmpLen; + + if (EFI_ERROR (RtcI2cWaitAccess ())) { + return EFI_DEVICE_ERROR; + } + + if (DataLen > sizeof (TmpBuf) - 1) { + return EFI_INVALID_PARAMETER; + } + + Status =3D I2cProbe (I2C_RTC_BUS_ADDRESS, I2C_RTC_BUS_SPEED); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // The first byte is the address + // + TmpBuf[0] =3D Addr; + TmpLen =3D DataLen + 1; + CopyMem ((VOID *)(TmpBuf + 1), (VOID *)Data, DataLen); + + Status =3D I2cWrite (I2C_RTC_BUS_ADDRESS, I2C_RTC_CHIP_ADDRESS, TmpBuf, = &TmpLen); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + * Returns the current time and date information of the hardware platform. + * + * @param Time A pointer to storage to receive a snapsho= t of the current time. + * + * + * @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 ha= rdware error. + */ +EFI_STATUS +EFIAPI +PlatformGetTime ( + OUT EFI_TIME *Time + ) +{ + EFI_STATUS Status; + UINT8 *Data; + + if (Time =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D RtcI2cRead (RTC_ADDR, RtcBufVir, RTC_DATA_BUF_LEN); + + Data =3D (UINT8 *)RtcBufVir; + if (Status =3D=3D EFI_SUCCESS) { + Time->Second =3D PCF85063_SEC_DEC (Data[PCF85063_OFFSET_SEC]); + Time->Minute =3D PCF85063_MIN_DEC (Data[PCF85063_OFFSET_MIN]); + Time->Hour =3D PCF85063_HR_DEC (Data[PCF85063_OFFSET_HR]); + Time->Day =3D PCF85063_DAY_DEC (Data[PCF85063_OFFSET_DAY]); + Time->Month =3D PCF85063_MON_DEC (Data[PCF85063_OFFSET_MON]); + Time->Year =3D PCF85063_YEA_DEC (Data[PCF85063_OFFSET_YEA]); + Time->Year +=3D RTC_DEFAULT_MIN_YEAR; + if (Time->Year > RTC_DEFAULT_MAX_YEAR) { + Time->Year =3D RTC_DEFAULT_MAX_YEAR; + } + if (Time->Year < RTC_DEFAULT_MIN_YEAR) { + Time->Year =3D RTC_DEFAULT_MIN_YEAR; + } + } + + return Status; +} + +/** + * Set the time and date information to the hardware platform. + * + * @param Time A pointer to storage to set the current t= ime to hardware platform. + * + * + * @retval EFI_SUCCESS The operation completed successfully. + * @retval EFI_INVALID_PARAMETER Time is NULL. + * @retval EFI_DEVICE_ERROR The time could not be set due due to hard= ware error. + **/ +EFI_STATUS +EFIAPI +PlatformSetTime ( + IN EFI_TIME *Time + ) +{ + UINT8 *Data; + + if (Time =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Time->Year < RTC_DEFAULT_MIN_YEAR || + Time->Year > RTC_DEFAULT_MAX_YEAR) + { + return EFI_INVALID_PARAMETER; + } + + Data =3D (UINT8 *)RtcBufVir; + Data[PCF85063_OFFSET_SEC] =3D PCF85063_SEC_ENC (Time->Second); + Data[PCF85063_OFFSET_MIN] =3D PCF85063_MIN_ENC (Time->Minute); + Data[PCF85063_OFFSET_HR] =3D PCF85063_HR_ENC (Time->Hour); + Data[PCF85063_OFFSET_DAY] =3D PCF85063_DAY_ENC (Time->Day); + Data[PCF85063_OFFSET_MON] =3D PCF85063_MON_ENC (Time->Month); + Data[PCF85063_OFFSET_YEA] =3D PCF85063_YEA_ENC (Time->Year - RTC_DEFAULT= _MIN_YEAR); + + return RtcI2cWrite (RTC_ADDR, RtcBufVir, RTC_DATA_BUF_LEN); +} + +/** + * Callback function for hardware platform to convert data pointers to vir= tual address + */ +VOID +EFIAPI +PlatformVirtualAddressChangeEvent ( + VOID + ) +{ + EfiConvertPointer (0x0, (VOID **)&RtcBufVir); +} + +/** + * Callback function for hardware platform to initialize private data + * + * + * @retval EFI_SUCCESS The operation completed successfully. + * @retval Others The error status indicates the error + */ +EFI_STATUS +EFIAPI +PlatformInitialize ( + VOID + ) +{ + EFI_STATUS Status; + + /* + * Allocate the buffer for RTC data + * The buffer can be accessible after ExitBootServices + */ + RtcBufVir =3D (UINT64)AllocateRuntimeZeroPool (RTC_DATA_BUF_LEN); + ASSERT_EFI_ERROR (RtcBufVir); + RtcBufPhy =3D (UINT64)RtcBufVir; + + Status =3D I2cSetupRuntime (I2C_RTC_BUS_ADDRESS); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a:%d I2cSetupRuntime() failed - %r \n", + __FUNCTION__, + __LINE__, + Status + )); + return Status; + } + + Status =3D GpioSetupRuntime (I2C_RTC_ACCESS_GPIO_PIN); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a:%d GpioSetupRuntime() failed - %r \n", + __FUNCTION__, + __LINE__, + Status + )); + return Status; + } + + return EFI_SUCCESS; +} diff --git a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85= 063RealTimeClockLib.c b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClo= ckLib/PCF85063RealTimeClockLib.c new file mode 100644 index 000000000000..ef8c71e92c18 --- /dev/null +++ b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063Real= TimeClockLib.c @@ -0,0 +1,257 @@ +/** @file + + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PCF85063.h" + +#define TICKS_PER_SEC (ArmGenericTimerGetTimerFreq ()) + +STATIC EFI_EVENT mVirtualAddressChangeEvent =3D NULL; + +STATIC UINT64 mLastSavedSystemCount =3D 0; +STATIC UINT64 mLastSavedTimeEpoch =3D 0; + +/** + * Returns the current time and date information, and the time-keeping cap= abilities + * of the hardware platform. + * + * @param Time A pointer to storage to receive a snapsho= t of the current time. + * @param Capabilities An optional pointer to a buffer to receiv= e 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 ha= rdware error. + */ +EFI_STATUS +EFIAPI +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +{ + EFI_STATUS Status; + UINT64 CurrentSystemCount; + UINT64 TimeElapsed; + UINTN EpochSeconds; + + if ((mLastSavedTimeEpoch =3D=3D 0) || EfiAtRuntime ()) { + Status =3D PlatformGetTime (Time); + if (EFI_ERROR (Status)) { + // Failed to read platform RTC so create fake time + Time->Second =3D 0; + Time->Minute =3D 0; + Time->Hour =3D 10; + Time->Day =3D 1; + Time->Month =3D 1; + Time->Year =3D 2017; + } + + EpochSeconds =3D EfiTimeToEpoch (Time); + if (!EfiAtRuntime ()) { + mLastSavedTimeEpoch =3D EpochSeconds; + mLastSavedSystemCount =3D ArmGenericTimerGetSystemCount (); + } + } else { + CurrentSystemCount =3D ArmGenericTimerGetSystemCount (); + if (CurrentSystemCount >=3D mLastSavedSystemCount) { + TimeElapsed =3D (CurrentSystemCount - mLastSavedSystemCount) / MultU= 64x32 (1, TICKS_PER_SEC); + EpochSeconds =3D mLastSavedTimeEpoch + TimeElapsed; + } else { + // System counter overflow 64 bits + // Call GetTime again to read the date from RTC HW, not using generi= c timer system counter + mLastSavedTimeEpoch =3D 0; + return LibGetTime (Time, Capabilities); + } + } + + // Adjust for the correct timezone + if (Time->TimeZone !=3D EFI_UNSPECIFIED_TIMEZONE) { + EpochSeconds +=3D Time->TimeZone * SEC_PER_MIN; + } + + // Adjust for the correct period + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) =3D=3D EFI_TIME_IN_DAYLIGHT)= { + // Convert to adjusted time, i.e. spring forwards one hour + EpochSeconds +=3D SEC_PER_HOUR; + } + + EpochToEfiTime (EpochSeconds, Time); + + return EFI_SUCCESS; +} + +/** + * 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 hard= ware error. + */ +EFI_STATUS +EFIAPI +LibSetTime ( + IN EFI_TIME *Time + ) +{ + EFI_STATUS Status; + UINTN EpochSeconds; + + EpochSeconds =3D EfiTimeToEpoch (Time); + + // Adjust for the correct time zone, i.e. convert to UTC time zone + if (Time->TimeZone !=3D EFI_UNSPECIFIED_TIMEZONE) { + EpochSeconds -=3D Time->TimeZone * SEC_PER_MIN; + } + + // Adjust for the correct period, i.e. fall back one hour + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) =3D=3D EFI_TIME_IN_DAYLIGHT)= { + EpochSeconds -=3D SEC_PER_HOUR; + } + + EpochToEfiTime (EpochSeconds, Time); + + Status =3D PlatformSetTime (Time); + if (EFI_ERROR (Status)) { + return Status; + } + + if (!EfiAtRuntime ()) { + mLastSavedTimeEpoch =3D EpochSeconds; + mLastSavedSystemCount =3D ArmGenericTimerGetSystemCount (); + } + + return EFI_SUCCESS; +} + +/** + * Returns the current wakeup alarm clock setting. + * + * @param Enabled Indicates if the alarm is currently enabl= ed 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 du= e 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 wa= keup alarm for. + * + * @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm = was enabled. If + * Enable is FALSE, then the wakeup alarm wa= s 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 p= latform. + */ +EFI_STATUS +EFIAPI +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ) +{ + return EFI_UNSUPPORTED; +} + +/** + 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 phy= sical addresses + // to virtual address. After the OS transitions to calling in virtual mo= de, all future + // runtime calls will be made in virtual mode. + // + PlatformVirtualAddressChangeEvent (); +} + +/** + * This is the declaration of an EFI image entry point. This can be the en= try point to an application + * written to this specification, an EFI boot service driver, or an EFI ru= ntime 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; + + Status =3D PlatformInitialize (); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Register for the virtual address change event + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + LibRtcVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mVirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} --=20 2.17.1