From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM02-DM3-obe.outbound.protection.outlook.com (NAM02-DM3-obe.outbound.protection.outlook.com [40.107.95.96]) by mx.groups.io with SMTP id smtpd.web08.247.1623775691194077796 for ; Tue, 15 Jun 2021 09:48:11 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@os.amperecomputing.com header.s=selector2 header.b=M5D1b9V+; spf=pass (domain: os.amperecomputing.com, ip: 40.107.95.96, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=fv8IXcodyjS4ld0jpmYIr+4UFpvSDxoteNw5BhXX17gR/1i+4KSIGiPBs5Ed8jr5zet0XhYCOgUuZZGvuXjrb4mxnpRFmmf50OgHdexgs9WcyqAyE59DivsS7DBzu5GX+5APn5/fsNPUnU3MIWq+ZkXdM0V+t5Cu1CX6J/rDrJ4Y07VaQdZSA5V2YnZT5jb22gfUtoLLXIK8H6z91/QMchFDoAgsP73aNj1fukuifGNbJ7TUzsCWBRJy7lySP5PUrrTUayoW0CP/iIxbcXXtNPOto95lP/AbYRLsEilcziVA6qXrz8FaNQ5BnfrrfF57FOacNX/QlObmgeTjpkWOhw== 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-SenderADCheck; bh=xmIseeM3wxGEvV8AfjolfGUqU4EQ7FQEJHFXiO2LyxM=; b=FEIpQqwXVt4DJxlgOJCOlCjKjMIkro7WbFawHaI2u+zPa8QOvTsucZPaWoe8uN8OPORCrP9uqMrway2tdfOsiLQ03kK7EkDkXgrUYkIo3GIaSZTRAwElT66ALH8hBHFTpgbVT6L4VK7vfzDnp0OcG/LD+9htFYOWfM5Kd31TqooFzKih2YAl7IPcuzRVkt6opllUGeCuyB6DVoQD/hl4c3e/7dEwbqbZOZXrY7ffxfdJ5xf+q7657o8n9JOLraoJpS7+IGjbZb2a3rQtgLytV7TKshmPlu/BqpuPOkhfF9u/WTsbm2X4YFEAMWbtmy3n6dPkS3dOrOL4S2XkYTX8xQ== 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=xmIseeM3wxGEvV8AfjolfGUqU4EQ7FQEJHFXiO2LyxM=; b=M5D1b9V+k7UaafZjzHyTLvFaJVmxYHsDWDPEY9mGK3BOVl/F4O5/Bc3xOQu6AdXFo9rzDYcdrPWBQ6K0HIKLHhd3GTyQBqvO0M/63hVVxeKHz9IFllBHnEYpVboleTgqe1NPNLu6ip0kikfXvRAgpSsraZ4XlCdi+DRiV7x8Y3Q= Authentication-Results: intel.com; dkim=none (message not signed) header.d=none;intel.com; dmarc=none action=none header.from=os.amperecomputing.com; Received: from DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) by DM5PR01MB2427.prod.exchangelabs.com (2603:10b6:3:48::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4219.24; Tue, 15 Jun 2021 16:48:09 +0000 Received: from DM6PR01MB5849.prod.exchangelabs.com ([fe80::4d8d:74e3:6747:75a2]) by DM6PR01MB5849.prod.exchangelabs.com ([fe80::4d8d:74e3:6747:75a2%7]) with mapi id 15.20.4219.025; Tue, 15 Jun 2021 16:48:09 +0000 Subject: Re: [edk2-platforms][PATCH v2 07/32] JadePkg: Implement RealTimeClockLib for PCF85063 To: Leif Lindholm Cc: devel@edk2.groups.io, Vu Nguyen , Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone References: <20210526100724.5359-1-nhi@os.amperecomputing.com> <20210526100724.5359-9-nhi@os.amperecomputing.com> <20210604232615.zdpphdmxdj3kvg37@leviathan> From: "Nhi Pham" Message-ID: Date: Tue, 15 Jun 2021 23:48:00 +0700 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Thunderbird/78.11.0 In-Reply-To: <20210604232615.zdpphdmxdj3kvg37@leviathan> X-Originating-IP: [116.110.40.240] X-ClientProxiedBy: HKAPR03CA0017.apcprd03.prod.outlook.com (2603:1096:203:c8::22) To DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from [192.168.1.7] (116.110.40.240) by HKAPR03CA0017.apcprd03.prod.outlook.com (2603:1096:203:c8::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4242.9 via Frontend Transport; Tue, 15 Jun 2021 16:48:06 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 2a136f69-6b05-4161-4b08-08d9301d5add X-MS-TrafficTypeDiagnostic: DM5PR01MB2427: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:2512; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 8KAG81Eo4sRJndCRd2snOkFPLkeNZxs/kR307fzYrHu1yA7iKEbiPbgrhfl5qsFnEuAnCoj1z7vlCEDdbKhiS36qATTlXXiNno8znfWNP/QiHxQXGmLNhleAI0pZgTeGOmZ9UaDg6jpULUUZl80Oq3H5RTioD/hKduWyY2dYMBweeJIB3mTMBuFvLSuUtf1vG2bPrDOL3Efpt8fPMBlmlnRlmR5/YMT9nXFPlG89gnUpUcPhPOn+AJRUT4yEcphAioKoxkZgrca8qovcQamlan7g3g0FiiJ0m8yQOEdHFuKDr59BN16AEKaXD3d0RBY1bQDs7zr/amweKKOjqU6DNI9SjSoyezRuboYaBp1syRaVVhezNmqcHV/W9Nh4yA8JefTJRdrzg5cZRjjc0k599Laf4/C14iWyo2XE49VrMRqoUJhVqLfKnkBNRQR1usaOLHounuVcxI9mu2te7Xu899KiTDulcuLmeLB/i5nNstaNpIEmLKSQZ6z3DospYky0/CKHQj2YVlURZSazOMhLVS8tdIKDD5XxDNmjAjncw/BQnE9o6PmYc6rqzs2M0BmKkZlvX2DbSSl1l6CpChuOjt85DlPXDq/UVJAhPiHcQE+VXb14ch/E56f2RNZ/FdYvXD3JQfwCqNb/4hoTopfnkHXGmhD8UYtfGMptSTgNQ7fbI7L9T4W3SgiCrhNpkVx/pbcgDYHy/uvK3exefQiQDWArUUNIFwUqZBf4OH1rosQ= 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)(366004)(39840400004)(346002)(376002)(396003)(86362001)(316002)(8936002)(4326008)(54906003)(66946007)(16576012)(66556008)(6916009)(19627235002)(83380400001)(31686004)(30864003)(6666004)(5660300002)(53546011)(66476007)(6486002)(2616005)(8676002)(186003)(478600001)(956004)(16526019)(38350700002)(31696002)(38100700002)(2906002)(26005)(52116002)(43740500002)(45980500001);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?TWRJYXNpd0kwVHhxNTdaVFkvVGhKa2hlNkhjSWMyZGhRRGNRUDdLbTJGMGh3?= =?utf-8?B?eHA2SnRXTzJtU3hvWGlXdisrdERGYjlZc0pEZHh5TlJ1RXVLZzJBUTNMMHFj?= =?utf-8?B?QmdRRkkwL0d3Z3hlTmRlNzQ3c0VMZDVVbDJUQ1NjVUxiYXM5Nm1JbmdKaVJk?= =?utf-8?B?SmVZRDIyUkY2OXd6NHgyWllKblh0QVpocm9QVTlyTm9yQmt1U1FNekd5QlpH?= =?utf-8?B?UlI4dDN5RlJ4L1VWdFRzL1hmRkRlTGV6NWM1aWlyWHZXaDBoQTkvNFF3SHFL?= =?utf-8?B?c0pON2pZK1R3TUFWSEk1b1lyY0ZXbVp0elFjUHRYeThXcFdMeWFJVllqeWsr?= =?utf-8?B?bzQ0SjNEOS9XbFJ3ZlVXTXI2dVhlelM0TGhMNzJ6bFlHL252anVuZjd5eGk0?= =?utf-8?B?RDlJZDBmZ0VTYzFTTVFrb1FPTDZPNE9vREhyTHBscmpQbW52SUxpZS8yV1ZK?= =?utf-8?B?S3J4MjRpVVBCcjVSajRIV0tLalg3UVRIYmszMlFTWGNsTFJtSU4weWlKYnBj?= =?utf-8?B?Vll5TngxVWpBVitMK2lXNlpETEsrd3JUVnMvZkd1RHFEa1VxTFpGZTR6ODVo?= =?utf-8?B?RmpiS3J1WGdTK0ViZ3hQMWluY1pmdE1LYkpOa3dGRFJ5UjhURkgwaStza3J0?= =?utf-8?B?OEZJRjJrK2FSL0hwU2JKVDR2MDhHNEQ0NDNQM3kvM0ZwMHUvUU1mTHhVd0sx?= =?utf-8?B?c2tOcjBkeStKMmljNmhybG0yMXlKQzhQZGRqV0czc1FveENacTZ4SjJOWEhS?= =?utf-8?B?cC9BRGNhNWNHWDF6d2NWVElERVZJbVNZT1RZbVVETE01dWcwemx1OXZKRVEr?= =?utf-8?B?SWR4Zk5tNGYxSnFoNnBNaENORWQ3blU0Z1RucGhHUm5MaE9tVkt5aFNJbDBk?= =?utf-8?B?SkM5ZHduQjJpU3VSN2NlaWQzaGFZT2srTjJxUVNWOStjYnVyaVFDZ2l2NnA3?= =?utf-8?B?ZTN3K2Z5anhYWDkzN29MQzg0aDZ2OGxKb1I4L1laZmRwdkZHd3FMeVNVb0pI?= =?utf-8?B?YmN1OGI3czRoSWpyL09pWnBibEVHcDlqTktrdjg5WVRLUkhqbm4xSUVsWVlu?= =?utf-8?B?Qng2TjZYb1VMY3lyUEY5YitqUlRsZkJxN21rcUh5b295aHdUbEsyZ0I4N0lO?= =?utf-8?B?OXZnYlJWNVRoVDliNFJUeGhZTmpZdzVuMUpzdE52WDlTaXZWZi9yY1UyYURF?= =?utf-8?B?bkFQSTVLZXU2bmhWRTMxL1N4bzdkL3JwSyt2amJrR1dMQUM2eGszcGI4YnZP?= =?utf-8?B?cTUyZ1YwdDZhZjFaaElucDFsQXp1Z3Z6U2lMN3NSNExFS1M3dHA1STFhK0xo?= =?utf-8?B?YmRuL0VMTVBMa2Q2bUJ0ZEFNNWEwNXdIZXpWVy83VXJpUmdRT2p1Y1JGWGRB?= =?utf-8?B?ZHNjRGJBM0tPd0ZRNVdDY250OUZYbDkyNnBobUNBeVdjenNhMzFyY2hmQ0FY?= =?utf-8?B?RkRlYnVXOFlCOE5Yb2t6ZDlhWk9wRlBkQUFBK09YK0tNSmZrbVVrU3VHZTFO?= =?utf-8?B?SWZ0N25yM2laOTRXN0VadzN2MEQyN3lYa3hEaGhjNUw1TVU2d2JnbE5yeDVi?= =?utf-8?B?NUZaZnYzYzRQVmJiQWMzb0ZhZXJEM2FkZjZMMmlyMkZWcUIwSXNOYWRFTlVk?= =?utf-8?B?a2VYd0Y3eFdybjZaSXYxbE85VXdVQ1hkTzZha1VFY05yODllY0UwdVROU2s0?= =?utf-8?B?b2JlcUJ3bkFVNDA2TXhiK0VjUHJWU1FrcjBxc0NGdlVpQ3lvQXgzMFdjcHE5?= =?utf-8?Q?tGXI3R/9T3huCzehlFqMfge2FwfSn0OS1E9NT9G?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2a136f69-6b05-4161-4b08-08d9301d5add X-MS-Exchange-CrossTenant-AuthSource: DM6PR01MB5849.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Jun 2021 16:48:08.9271 (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: 6EpdoS+EUqVsEgAL5JkGz6zDnuZ3ASg6AXPfwpmWolr9wfckZe4pefpUcNXdqmziVPAdtkM+YvsabHwWx4L/AnCul4C9/s5kHf8nYgX0+5Y= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR01MB2427 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-Language: en-US On 6/5/21 06:26, Leif Lindholm wrote: > On Wed, May 26, 2021 at 17:06:59 +0700, Nhi Pham wrote: >> 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 >> --- >> Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 2 + >> Platform/Ampere/JadePkg/Jade.dsc | 2 +- >> Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf | 44 +++ >> Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h | 91 ++++++ >> Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c | 317 ++++++++++++++++++++ >> Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.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 6a6f72e995af..9f19f495fad2 100755 >> --- 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/SystemFirmwareInterfaceLib/SystemFirmwareInterfaceLib.inf >> AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.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/MmCommunicationLib/MmCommunicationLib.inf >> >> # >> diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc >> index f92855af99ab..f37ab1a92e44 100755 >> --- a/Platform/Ampere/JadePkg/Jade.dsc >> +++ b/Platform/Ampere/JadePkg/Jade.dsc >> @@ -73,7 +73,7 @@ [LibraryClasses] >> # >> # RTC Library: Common RTC >> # >> - RealTimeClockLib|EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf >> + RealTimeClockLib|Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf >> >> # >> # Library for FailSafe support >> diff --git a/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf >> new file mode 100644 >> index 000000000000..1fe561cc0ec9 >> --- /dev/null >> +++ b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.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 = 0x0001001B >> + MODULE_TYPE = BASE >> + BASE_NAME = PCF85063RealTimeClockLib >> + FILE_GUID = 271569F6-5522-4006-9FF5-F07A59473AAC >> + LIBRARY_CLASS = RealTimeClockLib >> + VERSION_STRING = 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/PCF85063.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 snapshot 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 hardware 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 time 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 hardware error. >> + **/ >> +EFI_STATUS >> +EFIAPI >> +PlatformSetTime ( >> + IN EFI_TIME *Time >> + ); >> + >> +/** >> + * Callback function for hardware platform to convert data pointers to virtual 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/PCF85063.c b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c >> new file mode 100644 >> index 000000000000..f9fa125d9d7e >> --- /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)) > *twitch* > Please add that space before '*' like on all other lines. Thanks. Will fix it in the v3. Best regards, Nhi > > With that: > Reviewed-by: Leif Lindholm > > / > Leif > >> +#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 = RTC_TIMEOUT_WAIT_ACCESS; >> + while ((GpioReadBit (I2C_RTC_ACCESS_GPIO_PIN) != 0) && (Timeout > 0)) { >> + MicroSecondDelay (100); >> + Timeout -= 100; >> + } >> + >> + if (Timeout <= 0) { >> + DEBUG ((DEBUG_ERROR, "%a: Timeout while waiting access RTC\n", __FUNCTION__)); >> + 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 = I2cProbe (I2C_RTC_BUS_ADDRESS, I2C_RTC_BUS_SPEED); >> + if (EFI_ERROR (Status)) { >> + return EFI_DEVICE_ERROR; >> + } >> + >> + // >> + // Send the slave address for read >> + // >> + TmpLen = 1; >> + Status = 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 = 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 = 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] = Addr; >> + TmpLen = DataLen + 1; >> + CopyMem ((VOID *)(TmpBuf + 1), (VOID *)Data, DataLen); >> + >> + Status = 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 snapshot 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 hardware error. >> + */ >> +EFI_STATUS >> +EFIAPI >> +PlatformGetTime ( >> + OUT EFI_TIME *Time >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT8 *Data; >> + >> + if (Time == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Status = RtcI2cRead (RTC_ADDR, RtcBufVir, RTC_DATA_BUF_LEN); >> + >> + Data = (UINT8 *)RtcBufVir; >> + if (Status == EFI_SUCCESS) { >> + Time->Second = PCF85063_SEC_DEC (Data[PCF85063_OFFSET_SEC]); >> + Time->Minute = PCF85063_MIN_DEC (Data[PCF85063_OFFSET_MIN]); >> + Time->Hour = PCF85063_HR_DEC (Data[PCF85063_OFFSET_HR]); >> + Time->Day = PCF85063_DAY_DEC (Data[PCF85063_OFFSET_DAY]); >> + Time->Month = PCF85063_MON_DEC (Data[PCF85063_OFFSET_MON]); >> + Time->Year = PCF85063_YEA_DEC (Data[PCF85063_OFFSET_YEA]); >> + Time->Year += RTC_DEFAULT_MIN_YEAR; >> + if (Time->Year > RTC_DEFAULT_MAX_YEAR) { >> + Time->Year = RTC_DEFAULT_MAX_YEAR; >> + } >> + if (Time->Year < RTC_DEFAULT_MIN_YEAR) { >> + Time->Year = 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 time 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 hardware error. >> + **/ >> +EFI_STATUS >> +EFIAPI >> +PlatformSetTime ( >> + IN EFI_TIME *Time >> + ) >> +{ >> + UINT8 *Data; >> + >> + if (Time == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + if (Time->Year < RTC_DEFAULT_MIN_YEAR || >> + Time->Year > RTC_DEFAULT_MAX_YEAR) >> + { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Data = (UINT8 *)RtcBufVir; >> + Data[PCF85063_OFFSET_SEC] = PCF85063_SEC_ENC (Time->Second); >> + Data[PCF85063_OFFSET_MIN] = PCF85063_MIN_ENC (Time->Minute); >> + Data[PCF85063_OFFSET_HR] = PCF85063_HR_ENC (Time->Hour); >> + Data[PCF85063_OFFSET_DAY] = PCF85063_DAY_ENC (Time->Day); >> + Data[PCF85063_OFFSET_MON] = PCF85063_MON_ENC (Time->Month); >> + Data[PCF85063_OFFSET_YEA] = 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 virtual 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 = (UINT64)AllocateRuntimeZeroPool (RTC_DATA_BUF_LEN); >> + ASSERT_EFI_ERROR (RtcBufVir); >> + RtcBufPhy = (UINT64)RtcBufVir; >> + >> + Status = 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 = 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/PCF85063RealTimeClockLib.c b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.c >> new file mode 100755 >> index 000000000000..ef8c71e92c18 >> --- /dev/null >> +++ b/Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.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 = NULL; >> + >> +STATIC UINT64 mLastSavedSystemCount = 0; >> +STATIC UINT64 mLastSavedTimeEpoch = 0; >> + >> +/** >> + * 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; >> + UINT64 CurrentSystemCount; >> + UINT64 TimeElapsed; >> + UINTN EpochSeconds; >> + >> + if ((mLastSavedTimeEpoch == 0) || EfiAtRuntime ()) { >> + Status = PlatformGetTime (Time); >> + if (EFI_ERROR (Status)) { >> + // Failed to read platform RTC so create fake time >> + Time->Second = 0; >> + Time->Minute = 0; >> + Time->Hour = 10; >> + Time->Day = 1; >> + Time->Month = 1; >> + Time->Year = 2017; >> + } >> + >> + EpochSeconds = EfiTimeToEpoch (Time); >> + if (!EfiAtRuntime ()) { >> + mLastSavedTimeEpoch = EpochSeconds; >> + mLastSavedSystemCount = ArmGenericTimerGetSystemCount (); >> + } >> + } else { >> + CurrentSystemCount = ArmGenericTimerGetSystemCount (); >> + if (CurrentSystemCount >= mLastSavedSystemCount) { >> + TimeElapsed = (CurrentSystemCount - mLastSavedSystemCount) / MultU64x32 (1, TICKS_PER_SEC); >> + EpochSeconds = mLastSavedTimeEpoch + TimeElapsed; >> + } else { >> + // System counter overflow 64 bits >> + // Call GetTime again to read the date from RTC HW, not using generic timer system counter >> + mLastSavedTimeEpoch = 0; >> + return LibGetTime (Time, Capabilities); >> + } >> + } >> + >> + // Adjust for the correct timezone >> + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { >> + EpochSeconds += Time->TimeZone * SEC_PER_MIN; >> + } >> + >> + // Adjust for the correct period >> + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { >> + // Convert to adjusted time, i.e. spring forwards one hour >> + EpochSeconds += 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 hardware error. >> + */ >> +EFI_STATUS >> +EFIAPI >> +LibSetTime ( >> + IN EFI_TIME *Time >> + ) >> +{ >> + EFI_STATUS Status; >> + UINTN EpochSeconds; >> + >> + EpochSeconds = EfiTimeToEpoch (Time); >> + >> + // Adjust for the correct time zone, i.e. convert to UTC time zone >> + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { >> + EpochSeconds -= Time->TimeZone * SEC_PER_MIN; >> + } >> + >> + // Adjust for the correct period, i.e. fall back one hour >> + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { >> + EpochSeconds -= SEC_PER_HOUR; >> + } >> + >> + EpochToEfiTime (EpochSeconds, Time); >> + >> + Status = PlatformSetTime (Time); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + if (!EfiAtRuntime ()) { >> + mLastSavedTimeEpoch = EpochSeconds; >> + mLastSavedSystemCount = ArmGenericTimerGetSystemCount (); >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + * 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; >> +} >> + >> +/** >> + 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 physical addresses >> + // to virtual address. After the OS transitions to calling in virtual mode, 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 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; >> + >> + Status = PlatformInitialize (); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + // >> + // Register for the virtual address change event >> + // >> + Status = gBS->CreateEventEx ( >> + EVT_NOTIFY_SIGNAL, >> + TPL_NOTIFY, >> + LibRtcVirtualNotifyEvent, >> + NULL, >> + &gEfiEventVirtualAddressChangeGuid, >> + &mVirtualAddressChangeEvent >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + return EFI_SUCCESS; >> +} >> -- >> 2.17.1 >>