From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (NAM10-MW2-obe.outbound.protection.outlook.com [40.107.94.121]) by mx.groups.io with SMTP id smtpd.web11.9839.1631721581192250169 for ; Wed, 15 Sep 2021 08:59:41 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@os.amperecomputing.com header.s=selector2 header.b=E3AHPX/2; spf=pass (domain: os.amperecomputing.com, ip: 40.107.94.121, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=BQ8k6c24nkdNhVLCXx63NsAQr4D2D+aa4xFN76lPu7dOmDxVifBjkzw/gm9np2CSrMo5XZ8PCC/uxdqqso+tzU9Agu/6AQutAYNfnv+3PlGRz+KqfzC1R7M9PD/gA8bIwisjYjczRG487zVCpS9E15DScNYN4Wmxd96pjItfdKVq5ye+31vHPNuKECoXB4a/eo6Mw8Yj4eNcw4wYrzyI9QFLyQf6zlHcEdbb+u5y8/8e3/pKNCeBrJTJ2zF2icSv3v5TqZtc2uUJGZYYGdOQc1VDsxcyJX+P3XRgT9z+zQkAqzS/feeNs8XVRsweyztEtwtazQtaud63dm6kJJDMfA== 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; bh=u3ysgJ1NiXmHhT6ted83S8oDEHysOA64FW4TcOuKTX4=; b=d+ALDjv0vXUGYb/RsXgq+GAMVOXikXKTW7dfWAf4/rao+FM5aUehEjN1Ij69BNfDmFhTFP77QvzOMFh1J9bpICnC+h2rN8h3acdf7aoz6LwKInF+dv6kZyp38jmmkrDiJgwUeWzjq6t8NEd1PCT/yj59Vjmxfk6qtgZ0aYXNpr0DRwrHnuZHHJMVNXVdrQ9GmbX91IbIm1WWvH07yPLFSrYULDfBlaJFmRIt0Sznmv6neeXaraegDdPsxWd3uLqlKycAQoO6yLR1QOBg534cJAyY4BAOTGGOpIybUhxi8HiOHu+wNSQ7SvWvDobqbRFH0ZCbdQkfhjOX3KpieIi19g== 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=u3ysgJ1NiXmHhT6ted83S8oDEHysOA64FW4TcOuKTX4=; b=E3AHPX/25EPQUmnCHkbsIJed6tjdqg4TvoWMFjhJaxEJmj/r6mDIDmvzk6gWfl2RO4O2vwk8sIlL5Sq4P2iFJInV54TSuCeVoPtO+AXIECf9mhcoF4TSxTNyysyaR72L6zqA3cxCKEL6h6YDk+vbooLljrwXgBm0+AoCurGj8Zw= Authentication-Results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=os.amperecomputing.com; Received: from DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) by DM5PR0101MB3065.prod.exchangelabs.com (2603:10b6:4:33::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4500.15; Wed, 15 Sep 2021 15:59:36 +0000 Received: from DM6PR01MB5849.prod.exchangelabs.com ([fe80::8eb:704f:2ba7:9bc3]) by DM6PR01MB5849.prod.exchangelabs.com ([fe80::8eb:704f:2ba7:9bc3%4]) with mapi id 15.20.4523.014; Wed, 15 Sep 2021 15:59:36 +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: [PATCH v3 07/28] JadePkg: Implement RealTimeClockLib for PCF85063 Date: Wed, 15 Sep 2021 22:55:06 +0700 Message-ID: <20210915155527.8176-8-nhi@os.amperecomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210915155527.8176-1-nhi@os.amperecomputing.com> References: <20210915155527.8176-1-nhi@os.amperecomputing.com> X-ClientProxiedBy: HK2PR0302CA0012.apcprd03.prod.outlook.com (2603:1096:202::22) To DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 Received: from sw004.amperecomputing.com (118.69.219.201) by HK2PR0302CA0012.apcprd03.prod.outlook.com (2603:1096:202::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4544.5 via Frontend Transport; Wed, 15 Sep 2021 15:59:33 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: d410df8a-0655-44cf-2087-08d97861d10d X-MS-TrafficTypeDiagnostic: DM5PR0101MB3065: X-MS-Exchange-Transport-Forked: True 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: lJgvOKBEvjbUR2dcgLqGBQF6NWQTPyHS5g9JsXIFCdu3leL/Y/2uVUKRFB//0CkhqzPTLsQyPvQ3wr0TO1/2x05rDWjscIMTAt5f0mPVZUrXUPgFrR+QMVdlRyd5gDOfJcL5d9Aa7/3vweX7WydYT+RSQiIa60Wti2Z4xn/Grjd+854yKBy2HDAyH3ot3FhZTH95g4td4B/EthfoU9SSLugFnZu4sOr0kpvQV9hQIRstoLx8gUl5lSBtr6CuAW8MwHTiAz5A4yShRvqTYNoJiosR6pfMmo/fOTup8yCD11Mgp+bKLPOqZJU0m2Ie919u6vT4augmYazmMQVH0AdWelYNM2l3gB8lYBJR5gRt3xz8TU2jFjgoJQoTApSGblC8PtmpUlifd3/GdppLDqElC+Xzvlbp1Bkai2w6XvHiCT3waSXHW4SMS54OiDjffdCaKOoE22vzMa1xAJZYDlUcO6gNVfYjSSvaphzCYIYbd7oAJ3L/vk854x4+O26t250ucclmHqe/iMkP7rXzmGv5kvM7cMQy1GvBH7Fqu09uoci3rOodl1S7nAFS/4mBwmhjW1tWHoE+2wJx0ZcVrNVq5sIbu0H7K1TyEURvAJ0w3nkKBszR2dAFCT2cjUWQghDa9FX5LiEK19rpmrs6OesHBtbaEta5Z2GYBCG8MZPKGLzKXBjUoZmfBRXzz1NMzy9l5drGsEDCJ/jgCTIVwO+ZNA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR01MB5849.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(4636009)(136003)(346002)(396003)(366004)(376002)(39850400004)(2616005)(38100700002)(38350700002)(2906002)(6666004)(6916009)(83380400001)(30864003)(6512007)(26005)(8676002)(4326008)(186003)(19627235002)(8936002)(478600001)(6506007)(5660300002)(52116002)(1076003)(86362001)(316002)(66556008)(54906003)(956004)(6486002)(66476007)(66946007);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?fg6iH6wR4dInwUwkmjHXMtHfLcGUlHu3ruxkmJIK/ctVhhnY5UusC8go9btl?= =?us-ascii?Q?p41SRgdAR2UAsfhE51hkwL+PyDWYKLGfXfIyOrpcGpyZzHfHiDFjlFLF/4Ol?= =?us-ascii?Q?3fIkdGZOZ0xYDPWGLzHWpsMHN6ihHvwpioOcrU9ky5CdAae72XrgXGzkDpF7?= =?us-ascii?Q?zMbZV0SKIcUOWYFLKUt396AzhSKnmt28Nk7Vv1LRI/xEC0dUiVkT91ZNEh3W?= =?us-ascii?Q?7cRFg1zbQYYvLlV1/80nfHh1cT780A1JvrJrJagBQ1Euq93d7cWuDNKB6XMJ?= =?us-ascii?Q?UhWkWPk1K9ho8UDjtfmKbeNw6c2C4yBXQKE4UjbLUfvDrWuObghDuH25EIau?= =?us-ascii?Q?5XIH6CAdER/4fWIjjunm5qyX+VdyKYaMKSLWsfirmAktpRpMRzcYN9RbdD4D?= =?us-ascii?Q?dkcy5hbOOfXqRfnciIF1e/+qVYyGc/Yzgj2Rn1zLFyFxls4bvQCgYEDTEnKD?= =?us-ascii?Q?jc/+p410FaKzypWf51XvyJeBtNb5RtzgZeJIsUBfNdo5pLUIBha7FUdQ8gDC?= =?us-ascii?Q?mECCm7Ony4RJunzux0s+OUpOdxT7DrtK/qz8+QMcgT1CjlSzMNQfQ/PEkWPU?= =?us-ascii?Q?EZ6d0VhbPh5xZtn0sy7xNe/2pjkWgdCDRxxo7l5y1Aojg+VP+OjrHz1PJrPI?= =?us-ascii?Q?VIokcFxgR2fLyZBPw9pOFRxFWMGQYOFDGfjMfxr/YUPVrImK4wiTS2W1fxwQ?= =?us-ascii?Q?vqJtyy+LyX9/qI0llbLwd1AW2oeNRdSwNIgjPwsL0+IEVJGj8o2EcgWh9wpA?= =?us-ascii?Q?FzfUVGRAHAjorj3wexQaYFjfGQFEuwfa8zQHzcLF1l+BRun4/wh1drKQXaKs?= =?us-ascii?Q?R2lJUnziPSaqmMYe2ett1r9ovGN0U+fFCNm2PIJfQopTPNs8aWUmKEnxQJJ5?= =?us-ascii?Q?H8MdPkKaAdKwHn46UB0y5B3EE/x7T4mOEtpgk4ng4ANLn8IYSHr37hua6aZO?= =?us-ascii?Q?WjqEcytT97/ro7uBVvKaHlF11eSqiSfD2n9ND6WiWmn0cUMtnczFDXCnufX8?= =?us-ascii?Q?U04T1ptBfvC04LKV5Fd5WKipmrtSmYzoAmE/XnE6+NN2lkzBISLf1WW5pL69?= =?us-ascii?Q?ad+rgPEWAqhAifVnXNvnDDoNofS8NhUv+EcS/Gnx5HRdh9SehO1AMpu/0w0f?= =?us-ascii?Q?cnJyxMiMdbunFnzsUBX/xtHAS1A0+/CA2zI479dmBjeBBfmNkhuw76ivwDIL?= =?us-ascii?Q?uj+h1dZ/ocBWhZoqSveBoMYKlJ1v+pYRawL8d+UUkSxyUOdhkCHPIKMtsDK3?= =?us-ascii?Q?ebL8PEdq00GkqKT+gI0uzUHkAxQ2TPIh7gpAcj9z2KbAfg5aolDlxak8j/tX?= =?us-ascii?Q?nSL5roFpQAoGY6O3MQl+vC0n?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: d410df8a-0655-44cf-2087-08d97861d10d X-MS-Exchange-CrossTenant-AuthSource: DM6PR01MB5849.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2021 15:59:36.7782 (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: QEPcTsDHdjjyRZP5I5lSa9WoT+hHbK8+ACQ5pYnyc6cYnzadPaT6X8DjOXt7+fcymvKH3W74MFTgo7jpr2fGzRZMS+vqfk+/K5EGZsK1xv0= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR0101MB3065 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Vu Nguyen 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: Vu Nguyen 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 89c143cd28e6..5f7a56133777 100644 --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc @@ -84,6 +84,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 =20 # diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jad= e.dsc index 0681835dd175..332cd8ac0c8e 100644 --- a/Platform/Ampere/JadePkg/Jade.dsc +++ b/Platform/Ampere/JadePkg/Jade.dsc @@ -75,7 +75,7 @@ [LibraryClasses] # # RTC Library: Common RTC # - RealTimeClockLib|EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualReal= TimeClockLib.inf + RealTimeClockLib|Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLi= b/PCF85063RealTimeClockLib.inf =20 # # Library for FailSafe support 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