* [RFC edk2-platforms v1 0/2] Improve D0x @ 2020-05-18 13:37 Ming Huang 2020-05-18 13:37 ` [RFC edk2-platforms v1 1/2] Hisilicon/Library: Move two functions to RtcHelperLib Ming Huang 2020-05-18 13:37 ` [RFC edk2-platforms v1 2/2] Silicon/Hisilicon: Add RX8900RealTimeClockLib Ming Huang 0 siblings, 2 replies; 7+ messages in thread From: Ming Huang @ 2020-05-18 13:37 UTC (permalink / raw) To: devel, leif, ard.biesheuvel Cc: lidongzhan, songdongkuang, wanghuiqiang, qiuliangen Main Changes: 1 Extract RtcHelperLib from M41T83RealTimeClockLib; 2 Add RX8900RealTimeClockLib; Ming Huang (2): Hisilicon/Library: Move two functions to RtcHelperLib Silicon/Hisilicon: Add RX8900RealTimeClockLib Platform/Hisilicon/D06/D06.dsc | 1 + Silicon/Hisilicon/Include/Library/RtcHelperLib.h | 28 ++ Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c | 80 +--- Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf | 1 + Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h | 41 ++ Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c | 468 ++++++++++++++++++++ Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf | 33 ++ Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c | 94 ++++ Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf | 32 ++ 9 files changed, 699 insertions(+), 79 deletions(-) create mode 100644 Silicon/Hisilicon/Include/Library/RtcHelperLib.h create mode 100644 Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h create mode 100644 Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c create mode 100644 Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf create mode 100644 Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c create mode 100644 Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf -- 2.8.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC edk2-platforms v1 1/2] Hisilicon/Library: Move two functions to RtcHelperLib 2020-05-18 13:37 [RFC edk2-platforms v1 0/2] Improve D0x Ming Huang @ 2020-05-18 13:37 ` Ming Huang 2020-05-18 18:03 ` Leif Lindholm 2020-05-18 13:37 ` [RFC edk2-platforms v1 2/2] Silicon/Hisilicon: Add RX8900RealTimeClockLib Ming Huang 1 sibling, 1 reply; 7+ messages in thread From: Ming Huang @ 2020-05-18 13:37 UTC (permalink / raw) To: devel, leif, ard.biesheuvel Cc: lidongzhan, songdongkuang, wanghuiqiang, qiuliangen The functions of acquiring ownership of RTC will be used for other RTC library, so move them to RtcHelperLib. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ming Huang <huangming23@huawei.com> --- Platform/Hisilicon/D06/D06.dsc | 1 + Silicon/Hisilicon/Include/Library/RtcHelperLib.h | 28 ++++++ Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c | 80 +---------------- Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf | 1 + Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c | 94 ++++++++++++++++++++ Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf | 32 +++++++ 6 files changed, 157 insertions(+), 79 deletions(-) diff --git a/Platform/Hisilicon/D06/D06.dsc b/Platform/Hisilicon/D06/D06.dsc index 000a4ee..eb20224 100644 --- a/Platform/Hisilicon/D06/D06.dsc +++ b/Platform/Hisilicon/D06/D06.dsc @@ -54,6 +54,7 @@ CpldIoLib|Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf + RtcHelperLib|Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf RealTimeClockLib|Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf OemMiscLib|Platform/Hisilicon/D06/Library/OemMiscLibD06/OemMiscLibD06.inf OemAddressMapLib|Platform/Hisilicon/D06/Library/OemAddressMapD06/OemAddressMapD06.inf diff --git a/Silicon/Hisilicon/Include/Library/RtcHelperLib.h b/Silicon/Hisilicon/Include/Library/RtcHelperLib.h new file mode 100644 index 0000000..d6c1d39 --- /dev/null +++ b/Silicon/Hisilicon/Include/Library/RtcHelperLib.h @@ -0,0 +1,28 @@ +/** @file + + Copyright (c) 2018, Hisilicon Limited. All rights reserved.<BR> + Copyright (c) 2018, Linaro Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __RTC_HELPER_LIB_H__ +#define __RTC_HELPER_LIB_H__ + +// The delay is need for cpld and I2C. This is a empirical value. MemoryFence is no need. +#define RTC_DELAY_30_MS 30000 +// The delay is need for cpld and I2C. This is a empirical value. MemoryFence is no need. +#define RTC_DELAY_2_MACROSECOND 2 + +EFI_STATUS +SwitchRtcI2cChannelAndLock ( + VOID + ); + +VOID +ReleaseOwnershipOfRtc ( + VOID + ); + +#endif diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c index 5131ce7..e3fecac 100644 --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c @@ -11,10 +11,9 @@ #include <PiDxe.h> #include <Library/BaseLib.h> #include <Library/BaseMemoryLib.h> -#include <Library/CpldD06.h> -#include <Library/CpldIoLib.h> #include <Library/DebugLib.h> #include <Library/I2CLib.h> +#include <Library/RtcHelperLib.h> #include <Library/TimeBaseLib.h> #include <Library/TimerLib.h> #include <Library/UefiLib.h> @@ -26,70 +25,6 @@ extern I2C_DEVICE gRtcDevice; STATIC EFI_LOCK mRtcLock; -EFI_STATUS -SwitchRtcI2cChannelAndLock ( - VOID - ) -{ - UINT8 Temp; - UINT8 Count; - - for (Count = 0; Count < 100; Count++) { - // To get the other side's state is idle first - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); - if ((Temp & BIT3) != 0) { - (VOID) MicroSecondDelay (RTC_DELAY_30_MS); - // Try 100 times, if BMC has not released the bus, return preemption failed - if (Count == 99) { - if (!EfiAtRuntime ()) { - DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state 100 times fail!\n", - __FUNCTION__, __LINE__)); - } - return EFI_DEVICE_ERROR; - } - continue; - } - - // if BMC free the bus, can be set 1 preemption - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); - Temp = Temp | CPU_GET_I2C_CONTROL; - // CPU occupied RTC I2C State - WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); - (VOID) MicroSecondDelay (RTC_DELAY_2_MACROSECOND); - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); - // Is preempt success - if(CPU_GET_I2C_CONTROL == (Temp & CPU_GET_I2C_CONTROL)) { - break; - } - if (Count == 99) { - if (!EfiAtRuntime ()) { - DEBUG((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state fail !!! \n", - __FUNCTION__, __LINE__)); - } - return EFI_DEVICE_ERROR; - } - (VOID) MicroSecondDelay (RTC_DELAY_30_MS); - } - - //Polling BMC RTC I2C status - for (Count = 0; Count < 100; Count++) { - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); - if ((Temp & BIT3) == 0) { - return EFI_SUCCESS; - } - (VOID) MicroSecondDelay (RTC_DELAY_30_MS); - } - - //If the BMC occupies the RTC I2C Channel, write back the CPU side is idle - // or the subsequent BMC will not preempt - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); - Temp = Temp & (~CPU_GET_I2C_CONTROL); - WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); - - return EFI_NOT_READY; -} - - /** Read RTC content through its registers. @@ -136,19 +71,6 @@ RtcWrite ( return Status; } -VOID -ReleaseOwnershipOfRtc ( - VOID - ) -{ - UINT8 Temp; - - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); - Temp = Temp & ~CPU_GET_I2C_CONTROL; - WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); -} - - EFI_STATUS InitializeM41T83 ( VOID diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf index 9344c6d..5970c0e 100644 --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf @@ -31,6 +31,7 @@ I2CLib IoLib PcdLib + RtcHelperLib TimeBaseLib TimerLib UefiLib diff --git a/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c new file mode 100644 index 0000000..bc8e6c5 --- /dev/null +++ b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c @@ -0,0 +1,94 @@ +/** @file + + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Uefi.h> +#include <PiDxe.h> +#include <Library/BaseLib.h> +#include <Library/CpldD06.h> +#include <Library/CpldIoLib.h> +#include <Library/DebugLib.h> +#include <Library/RtcHelperLib.h> +#include <Library/TimeBaseLib.h> +#include <Library/TimerLib.h> +#include <Library/UefiRuntimeLib.h> + +EFI_STATUS +SwitchRtcI2cChannelAndLock ( + VOID + ) +{ + UINT8 Temp; + UINT8 Count; + + for (Count = 0; Count < 100; Count++) { + // To get the other side's state is idle first + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); + if ((Temp & BIT3) != 0) { + (VOID) MicroSecondDelay (RTC_DELAY_30_MS); + // Try 100 times, if BMC has not released the bus, return preemption failed + if (Count == 99) { + if (!EfiAtRuntime ()) { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state 100 times fail!\n", + __FUNCTION__, __LINE__)); + } + return EFI_DEVICE_ERROR; + } + continue; + } + + // if BMC free the bus, can be set 1 preemption + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); + Temp = Temp | CPU_GET_I2C_CONTROL; + // CPU occupied RTC I2C State + WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); + (VOID)MicroSecondDelay (RTC_DELAY_2_MACROSECOND); + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); + // Is preempt success + if (CPU_GET_I2C_CONTROL == (Temp & CPU_GET_I2C_CONTROL)) { + break; + } + if (Count == 99) { + if (!EfiAtRuntime ()) { + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state fail !!! \n", + __FUNCTION__, __LINE__)); + } + return EFI_DEVICE_ERROR; + } + (VOID)MicroSecondDelay (RTC_DELAY_30_MS); + } + + //Polling BMC RTC I2C status + for (Count = 0; Count < 100; Count++) { + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); + if ((Temp & BIT3) == 0) { + return EFI_SUCCESS; + } + (VOID)MicroSecondDelay (RTC_DELAY_30_MS); + } + + //If the BMC occupies the RTC I2C Channel, write back the CPU side is idle + // or the subsequent BMC will not preempt + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); + Temp = Temp & (~CPU_GET_I2C_CONTROL); + WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); + + return EFI_NOT_READY; +} + +VOID +ReleaseOwnershipOfRtc ( + VOID + ) +{ + UINT8 Temp; + + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); + Temp = Temp & ~CPU_GET_I2C_CONTROL; + WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); + return ; +} diff --git a/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf new file mode 100644 index 0000000..1a36e64 --- /dev/null +++ b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf @@ -0,0 +1,32 @@ +#/** @file +# +# Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = RtcHelperLib + FILE_GUID = 5cb1a98f-2408-4fef-b68f-d5d04ff6a91f + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RtcHelperLib + +[Sources.common] + RtcHelperLib.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + Platform/Hisilicon/D06/D06.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + CpldIoLib + DebugLib + IoLib + +[Depex] + TRUE -- 2.8.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC edk2-platforms v1 1/2] Hisilicon/Library: Move two functions to RtcHelperLib 2020-05-18 13:37 ` [RFC edk2-platforms v1 1/2] Hisilicon/Library: Move two functions to RtcHelperLib Ming Huang @ 2020-05-18 18:03 ` Leif Lindholm 2020-05-19 10:28 ` Ming Huang 0 siblings, 1 reply; 7+ messages in thread From: Leif Lindholm @ 2020-05-18 18:03 UTC (permalink / raw) To: Ming Huang Cc: devel, ard.biesheuvel, lidongzhan, songdongkuang, wanghuiqiang, qiuliangen On Mon, May 18, 2020 at 21:37:23 +0800, Ming Huang wrote: > The functions of acquiring ownership of RTC will be used for other > RTC library, so move them to RtcHelperLib. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Ming Huang <huangming23@huawei.com> > --- > Platform/Hisilicon/D06/D06.dsc | 1 + > Silicon/Hisilicon/Include/Library/RtcHelperLib.h | 28 ++++++ > Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c | 80 +---------------- > Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf | 1 + > Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c | 94 ++++++++++++++++++++ > Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf | 32 +++++++ > 6 files changed, 157 insertions(+), 79 deletions(-) > > diff --git a/Platform/Hisilicon/D06/D06.dsc b/Platform/Hisilicon/D06/D06.dsc > index 000a4ee..eb20224 100644 > --- a/Platform/Hisilicon/D06/D06.dsc > +++ b/Platform/Hisilicon/D06/D06.dsc > @@ -54,6 +54,7 @@ > CpldIoLib|Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf > > TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf > + RtcHelperLib|Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf > RealTimeClockLib|Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf > OemMiscLib|Platform/Hisilicon/D06/Library/OemMiscLibD06/OemMiscLibD06.inf > OemAddressMapLib|Platform/Hisilicon/D06/Library/OemAddressMapD06/OemAddressMapD06.inf > diff --git a/Silicon/Hisilicon/Include/Library/RtcHelperLib.h b/Silicon/Hisilicon/Include/Library/RtcHelperLib.h > new file mode 100644 > index 0000000..d6c1d39 > --- /dev/null > +++ b/Silicon/Hisilicon/Include/Library/RtcHelperLib.h > @@ -0,0 +1,28 @@ > +/** @file > + > + Copyright (c) 2018, Hisilicon Limited. All rights reserved.<BR> > + Copyright (c) 2018, Linaro Limited. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef __RTC_HELPER_LIB_H__ > +#define __RTC_HELPER_LIB_H__ Please drop leading __ from macros. Those are reserved for toolchain use. > + > +// The delay is need for cpld and I2C. This is a empirical value. MemoryFence is no need. > +#define RTC_DELAY_30_MS 30000 > +// The delay is need for cpld and I2C. This is a empirical value. MemoryFence is no need. > +#define RTC_DELAY_2_MACROSECOND 2 I guess MACROSECOND is a typo for MICROSECOND? But we are now duplicating these macros between M41T83RealTimeClock.h and RtcHelperLib.h. And M41T83RealTimeClock.h still holds a bunch of other _MACROSECOND #defines. Could we move all of the macro definitions to this file instead? Could we also fix the spelling, in a patch preceding this one? / Leif > + > +EFI_STATUS > +SwitchRtcI2cChannelAndLock ( > + VOID > + ); > + > +VOID > +ReleaseOwnershipOfRtc ( > + VOID > + ); > + > +#endif > diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c > index 5131ce7..e3fecac 100644 > --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c > +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c > @@ -11,10 +11,9 @@ > #include <PiDxe.h> > #include <Library/BaseLib.h> > #include <Library/BaseMemoryLib.h> > -#include <Library/CpldD06.h> > -#include <Library/CpldIoLib.h> > #include <Library/DebugLib.h> > #include <Library/I2CLib.h> > +#include <Library/RtcHelperLib.h> > #include <Library/TimeBaseLib.h> > #include <Library/TimerLib.h> > #include <Library/UefiLib.h> > @@ -26,70 +25,6 @@ extern I2C_DEVICE gRtcDevice; > > STATIC EFI_LOCK mRtcLock; > > -EFI_STATUS > -SwitchRtcI2cChannelAndLock ( > - VOID > - ) > -{ > - UINT8 Temp; > - UINT8 Count; > - > - for (Count = 0; Count < 100; Count++) { > - // To get the other side's state is idle first > - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > - if ((Temp & BIT3) != 0) { > - (VOID) MicroSecondDelay (RTC_DELAY_30_MS); > - // Try 100 times, if BMC has not released the bus, return preemption failed > - if (Count == 99) { > - if (!EfiAtRuntime ()) { > - DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state 100 times fail!\n", > - __FUNCTION__, __LINE__)); > - } > - return EFI_DEVICE_ERROR; > - } > - continue; > - } > - > - // if BMC free the bus, can be set 1 preemption > - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > - Temp = Temp | CPU_GET_I2C_CONTROL; > - // CPU occupied RTC I2C State > - WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); > - (VOID) MicroSecondDelay (RTC_DELAY_2_MACROSECOND); > - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > - // Is preempt success > - if(CPU_GET_I2C_CONTROL == (Temp & CPU_GET_I2C_CONTROL)) { > - break; > - } > - if (Count == 99) { > - if (!EfiAtRuntime ()) { > - DEBUG((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state fail !!! \n", > - __FUNCTION__, __LINE__)); > - } > - return EFI_DEVICE_ERROR; > - } > - (VOID) MicroSecondDelay (RTC_DELAY_30_MS); > - } > - > - //Polling BMC RTC I2C status > - for (Count = 0; Count < 100; Count++) { > - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > - if ((Temp & BIT3) == 0) { > - return EFI_SUCCESS; > - } > - (VOID) MicroSecondDelay (RTC_DELAY_30_MS); > - } > - > - //If the BMC occupies the RTC I2C Channel, write back the CPU side is idle > - // or the subsequent BMC will not preempt > - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > - Temp = Temp & (~CPU_GET_I2C_CONTROL); > - WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); > - > - return EFI_NOT_READY; > -} > - > - > /** > Read RTC content through its registers. > > @@ -136,19 +71,6 @@ RtcWrite ( > return Status; > } > > -VOID > -ReleaseOwnershipOfRtc ( > - VOID > - ) > -{ > - UINT8 Temp; > - > - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > - Temp = Temp & ~CPU_GET_I2C_CONTROL; > - WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); > -} > - > - > EFI_STATUS > InitializeM41T83 ( > VOID > diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf > index 9344c6d..5970c0e 100644 > --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf > +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf > @@ -31,6 +31,7 @@ > I2CLib > IoLib > PcdLib > + RtcHelperLib > TimeBaseLib > TimerLib > UefiLib > diff --git a/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c > new file mode 100644 > index 0000000..bc8e6c5 > --- /dev/null > +++ b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c > @@ -0,0 +1,94 @@ > +/** @file > + > + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <Uefi.h> > +#include <PiDxe.h> > +#include <Library/BaseLib.h> > +#include <Library/CpldD06.h> > +#include <Library/CpldIoLib.h> > +#include <Library/DebugLib.h> > +#include <Library/RtcHelperLib.h> > +#include <Library/TimeBaseLib.h> > +#include <Library/TimerLib.h> > +#include <Library/UefiRuntimeLib.h> > + > +EFI_STATUS > +SwitchRtcI2cChannelAndLock ( > + VOID > + ) > +{ > + UINT8 Temp; > + UINT8 Count; > + > + for (Count = 0; Count < 100; Count++) { > + // To get the other side's state is idle first > + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > + if ((Temp & BIT3) != 0) { > + (VOID) MicroSecondDelay (RTC_DELAY_30_MS); > + // Try 100 times, if BMC has not released the bus, return preemption failed > + if (Count == 99) { > + if (!EfiAtRuntime ()) { > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state 100 times fail!\n", > + __FUNCTION__, __LINE__)); > + } > + return EFI_DEVICE_ERROR; > + } > + continue; > + } > + > + // if BMC free the bus, can be set 1 preemption > + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > + Temp = Temp | CPU_GET_I2C_CONTROL; > + // CPU occupied RTC I2C State > + WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); > + (VOID)MicroSecondDelay (RTC_DELAY_2_MACROSECOND); > + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > + // Is preempt success > + if (CPU_GET_I2C_CONTROL == (Temp & CPU_GET_I2C_CONTROL)) { > + break; > + } > + if (Count == 99) { > + if (!EfiAtRuntime ()) { > + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state fail !!! \n", > + __FUNCTION__, __LINE__)); > + } > + return EFI_DEVICE_ERROR; > + } > + (VOID)MicroSecondDelay (RTC_DELAY_30_MS); > + } > + > + //Polling BMC RTC I2C status > + for (Count = 0; Count < 100; Count++) { > + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > + if ((Temp & BIT3) == 0) { > + return EFI_SUCCESS; > + } > + (VOID)MicroSecondDelay (RTC_DELAY_30_MS); > + } > + > + //If the BMC occupies the RTC I2C Channel, write back the CPU side is idle > + // or the subsequent BMC will not preempt > + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > + Temp = Temp & (~CPU_GET_I2C_CONTROL); > + WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); > + > + return EFI_NOT_READY; > +} > + > +VOID > +ReleaseOwnershipOfRtc ( > + VOID > + ) > +{ > + UINT8 Temp; > + > + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); > + Temp = Temp & ~CPU_GET_I2C_CONTROL; > + WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); > + return ; > +} > diff --git a/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf > new file mode 100644 > index 0000000..1a36e64 > --- /dev/null > +++ b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf > @@ -0,0 +1,32 @@ > +#/** @file > +# > +# Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +#**/ > + > +[Defines] > + INF_VERSION = 0x0001001A > + BASE_NAME = RtcHelperLib > + FILE_GUID = 5cb1a98f-2408-4fef-b68f-d5d04ff6a91f > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = RtcHelperLib > + > +[Sources.common] > + RtcHelperLib.c > + > +[Packages] > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + Platform/Hisilicon/D06/D06.dec > + Silicon/Hisilicon/HisiPkg.dec > + > +[LibraryClasses] > + CpldIoLib > + DebugLib > + IoLib > + > +[Depex] > + TRUE > -- > 2.8.1 > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC edk2-platforms v1 1/2] Hisilicon/Library: Move two functions to RtcHelperLib 2020-05-18 18:03 ` Leif Lindholm @ 2020-05-19 10:28 ` Ming Huang 0 siblings, 0 replies; 7+ messages in thread From: Ming Huang @ 2020-05-19 10:28 UTC (permalink / raw) To: Leif Lindholm Cc: devel, ard.biesheuvel, lidongzhan, songdongkuang, wanghuiqiang, qiuliangen 在 2020/5/19 2:03, Leif Lindholm 写道: > On Mon, May 18, 2020 at 21:37:23 +0800, Ming Huang wrote: >> The functions of acquiring ownership of RTC will be used for other >> RTC library, so move them to RtcHelperLib. >> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Ming Huang <huangming23@huawei.com> >> --- >> Platform/Hisilicon/D06/D06.dsc | 1 + >> Silicon/Hisilicon/Include/Library/RtcHelperLib.h | 28 ++++++ >> Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c | 80 +---------------- >> Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf | 1 + >> Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c | 94 ++++++++++++++++++++ >> Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf | 32 +++++++ >> 6 files changed, 157 insertions(+), 79 deletions(-) >> >> diff --git a/Platform/Hisilicon/D06/D06.dsc b/Platform/Hisilicon/D06/D06.dsc >> index 000a4ee..eb20224 100644 >> --- a/Platform/Hisilicon/D06/D06.dsc >> +++ b/Platform/Hisilicon/D06/D06.dsc >> @@ -54,6 +54,7 @@ >> CpldIoLib|Silicon/Hisilicon/Library/CpldIoLib/CpldIoLib.inf >> >> TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf >> + RtcHelperLib|Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf >> RealTimeClockLib|Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf >> OemMiscLib|Platform/Hisilicon/D06/Library/OemMiscLibD06/OemMiscLibD06.inf >> OemAddressMapLib|Platform/Hisilicon/D06/Library/OemAddressMapD06/OemAddressMapD06.inf >> diff --git a/Silicon/Hisilicon/Include/Library/RtcHelperLib.h b/Silicon/Hisilicon/Include/Library/RtcHelperLib.h >> new file mode 100644 >> index 0000000..d6c1d39 >> --- /dev/null >> +++ b/Silicon/Hisilicon/Include/Library/RtcHelperLib.h >> @@ -0,0 +1,28 @@ >> +/** @file >> + >> + Copyright (c) 2018, Hisilicon Limited. All rights reserved.<BR> >> + Copyright (c) 2018, Linaro Limited. All rights reserved.<BR> >> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#ifndef __RTC_HELPER_LIB_H__ >> +#define __RTC_HELPER_LIB_H__ > > Please drop leading __ from macros. Those are reserved for toolchain > use. Ok > >> + >> +// The delay is need for cpld and I2C. This is a empirical value. MemoryFence is no need. >> +#define RTC_DELAY_30_MS 30000 >> +// The delay is need for cpld and I2C. This is a empirical value. MemoryFence is no need. >> +#define RTC_DELAY_2_MACROSECOND 2 > > I guess MACROSECOND is a > typo for MICROSECOND? Yes, this is a typo. > > But we are now duplicating these macros between M41T83RealTimeClock.h > and RtcHelperLib.h. And M41T83RealTimeClock.h still holds a bunch of > other _MACROSECOND #defines. > > Could we move all of the macro definitions to this file instead? > Could we also fix the spelling, in a patch preceding this one? Ok, modify in v2. Thanks, Ming > > / > Leif > >> + >> +EFI_STATUS >> +SwitchRtcI2cChannelAndLock ( >> + VOID >> + ); >> + >> +VOID >> +ReleaseOwnershipOfRtc ( >> + VOID >> + ); >> + >> +#endif >> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c >> index 5131ce7..e3fecac 100644 >> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c >> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.c >> @@ -11,10 +11,9 @@ >> #include <PiDxe.h> >> #include <Library/BaseLib.h> >> #include <Library/BaseMemoryLib.h> >> -#include <Library/CpldD06.h> >> -#include <Library/CpldIoLib.h> >> #include <Library/DebugLib.h> >> #include <Library/I2CLib.h> >> +#include <Library/RtcHelperLib.h> >> #include <Library/TimeBaseLib.h> >> #include <Library/TimerLib.h> >> #include <Library/UefiLib.h> >> @@ -26,70 +25,6 @@ extern I2C_DEVICE gRtcDevice; >> >> STATIC EFI_LOCK mRtcLock; >> >> -EFI_STATUS >> -SwitchRtcI2cChannelAndLock ( >> - VOID >> - ) >> -{ >> - UINT8 Temp; >> - UINT8 Count; >> - >> - for (Count = 0; Count < 100; Count++) { >> - // To get the other side's state is idle first >> - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> - if ((Temp & BIT3) != 0) { >> - (VOID) MicroSecondDelay (RTC_DELAY_30_MS); >> - // Try 100 times, if BMC has not released the bus, return preemption failed >> - if (Count == 99) { >> - if (!EfiAtRuntime ()) { >> - DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state 100 times fail!\n", >> - __FUNCTION__, __LINE__)); >> - } >> - return EFI_DEVICE_ERROR; >> - } >> - continue; >> - } >> - >> - // if BMC free the bus, can be set 1 preemption >> - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> - Temp = Temp | CPU_GET_I2C_CONTROL; >> - // CPU occupied RTC I2C State >> - WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); >> - (VOID) MicroSecondDelay (RTC_DELAY_2_MACROSECOND); >> - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> - // Is preempt success >> - if(CPU_GET_I2C_CONTROL == (Temp & CPU_GET_I2C_CONTROL)) { >> - break; >> - } >> - if (Count == 99) { >> - if (!EfiAtRuntime ()) { >> - DEBUG((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state fail !!! \n", >> - __FUNCTION__, __LINE__)); >> - } >> - return EFI_DEVICE_ERROR; >> - } >> - (VOID) MicroSecondDelay (RTC_DELAY_30_MS); >> - } >> - >> - //Polling BMC RTC I2C status >> - for (Count = 0; Count < 100; Count++) { >> - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> - if ((Temp & BIT3) == 0) { >> - return EFI_SUCCESS; >> - } >> - (VOID) MicroSecondDelay (RTC_DELAY_30_MS); >> - } >> - >> - //If the BMC occupies the RTC I2C Channel, write back the CPU side is idle >> - // or the subsequent BMC will not preempt >> - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> - Temp = Temp & (~CPU_GET_I2C_CONTROL); >> - WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); >> - >> - return EFI_NOT_READY; >> -} >> - >> - >> /** >> Read RTC content through its registers. >> >> @@ -136,19 +71,6 @@ RtcWrite ( >> return Status; >> } >> >> -VOID >> -ReleaseOwnershipOfRtc ( >> - VOID >> - ) >> -{ >> - UINT8 Temp; >> - >> - Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> - Temp = Temp & ~CPU_GET_I2C_CONTROL; >> - WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); >> -} >> - >> - >> EFI_STATUS >> InitializeM41T83 ( >> VOID >> diff --git a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf >> index 9344c6d..5970c0e 100644 >> --- a/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf >> +++ b/Silicon/Hisilicon/Library/M41T83RealTimeClockLib/M41T83RealTimeClockLib.inf >> @@ -31,6 +31,7 @@ >> I2CLib >> IoLib >> PcdLib >> + RtcHelperLib >> TimeBaseLib >> TimerLib >> UefiLib >> diff --git a/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c >> new file mode 100644 >> index 0000000..bc8e6c5 >> --- /dev/null >> +++ b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.c >> @@ -0,0 +1,94 @@ >> +/** @file >> + >> + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> >> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#include <Uefi.h> >> +#include <PiDxe.h> >> +#include <Library/BaseLib.h> >> +#include <Library/CpldD06.h> >> +#include <Library/CpldIoLib.h> >> +#include <Library/DebugLib.h> >> +#include <Library/RtcHelperLib.h> >> +#include <Library/TimeBaseLib.h> >> +#include <Library/TimerLib.h> >> +#include <Library/UefiRuntimeLib.h> >> + >> +EFI_STATUS >> +SwitchRtcI2cChannelAndLock ( >> + VOID >> + ) >> +{ >> + UINT8 Temp; >> + UINT8 Count; >> + >> + for (Count = 0; Count < 100; Count++) { >> + // To get the other side's state is idle first >> + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> + if ((Temp & BIT3) != 0) { >> + (VOID) MicroSecondDelay (RTC_DELAY_30_MS); >> + // Try 100 times, if BMC has not released the bus, return preemption failed >> + if (Count == 99) { >> + if (!EfiAtRuntime ()) { >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state 100 times fail!\n", >> + __FUNCTION__, __LINE__)); >> + } >> + return EFI_DEVICE_ERROR; >> + } >> + continue; >> + } >> + >> + // if BMC free the bus, can be set 1 preemption >> + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> + Temp = Temp | CPU_GET_I2C_CONTROL; >> + // CPU occupied RTC I2C State >> + WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); >> + (VOID)MicroSecondDelay (RTC_DELAY_2_MACROSECOND); >> + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> + // Is preempt success >> + if (CPU_GET_I2C_CONTROL == (Temp & CPU_GET_I2C_CONTROL)) { >> + break; >> + } >> + if (Count == 99) { >> + if (!EfiAtRuntime ()) { >> + DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Clear cpu_i2c_rtc_state fail !!! \n", >> + __FUNCTION__, __LINE__)); >> + } >> + return EFI_DEVICE_ERROR; >> + } >> + (VOID)MicroSecondDelay (RTC_DELAY_30_MS); >> + } >> + >> + //Polling BMC RTC I2C status >> + for (Count = 0; Count < 100; Count++) { >> + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> + if ((Temp & BIT3) == 0) { >> + return EFI_SUCCESS; >> + } >> + (VOID)MicroSecondDelay (RTC_DELAY_30_MS); >> + } >> + >> + //If the BMC occupies the RTC I2C Channel, write back the CPU side is idle >> + // or the subsequent BMC will not preempt >> + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> + Temp = Temp & (~CPU_GET_I2C_CONTROL); >> + WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); >> + >> + return EFI_NOT_READY; >> +} >> + >> +VOID >> +ReleaseOwnershipOfRtc ( >> + VOID >> + ) >> +{ >> + UINT8 Temp; >> + >> + Temp = ReadCpldReg (CPLD_I2C_SWITCH_FLAG); >> + Temp = Temp & ~CPU_GET_I2C_CONTROL; >> + WriteCpldReg (CPLD_I2C_SWITCH_FLAG, Temp); >> + return ; >> +} >> diff --git a/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf >> new file mode 100644 >> index 0000000..1a36e64 >> --- /dev/null >> +++ b/Silicon/Hisilicon/Library/RtcHelperLib/RtcHelperLib.inf >> @@ -0,0 +1,32 @@ >> +#/** @file >> +# >> +# Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> >> +# >> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +# >> +#**/ >> + >> +[Defines] >> + INF_VERSION = 0x0001001A >> + BASE_NAME = RtcHelperLib >> + FILE_GUID = 5cb1a98f-2408-4fef-b68f-d5d04ff6a91f >> + MODULE_TYPE = BASE >> + VERSION_STRING = 1.0 >> + LIBRARY_CLASS = RtcHelperLib >> + >> +[Sources.common] >> + RtcHelperLib.c >> + >> +[Packages] >> + EmbeddedPkg/EmbeddedPkg.dec >> + MdePkg/MdePkg.dec >> + Platform/Hisilicon/D06/D06.dec >> + Silicon/Hisilicon/HisiPkg.dec >> + >> +[LibraryClasses] >> + CpldIoLib >> + DebugLib >> + IoLib >> + >> +[Depex] >> + TRUE >> -- >> 2.8.1 >> > > . > ^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC edk2-platforms v1 2/2] Silicon/Hisilicon: Add RX8900RealTimeClockLib 2020-05-18 13:37 [RFC edk2-platforms v1 0/2] Improve D0x Ming Huang 2020-05-18 13:37 ` [RFC edk2-platforms v1 1/2] Hisilicon/Library: Move two functions to RtcHelperLib Ming Huang @ 2020-05-18 13:37 ` Ming Huang 2020-05-18 18:13 ` Leif Lindholm 1 sibling, 1 reply; 7+ messages in thread From: Ming Huang @ 2020-05-18 13:37 UTC (permalink / raw) To: devel, leif, ard.biesheuvel Cc: lidongzhan, songdongkuang, wanghuiqiang, qiuliangen There are some boards base on D06, but use RX8900 RTC, so upstream the RX8900RealTimeClockLib. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ming Huang <huangming23@huawei.com> --- Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h | 41 ++ Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c | 468 ++++++++++++++++++++ Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf | 33 ++ 3 files changed, 542 insertions(+) diff --git a/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h new file mode 100644 index 0000000..6bcef10 --- /dev/null +++ b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h @@ -0,0 +1,41 @@ +/** @file + + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __RX8900_REAL_TIME_CLOCK_H__ +#define __RX8900_REAL_TIME_CLOCK_H__ + +#define RX8900_REGADDR_SECONDS 0x00 +#define RX8900_REGADDR_MIUTES 0x01 +#define RX8900_REGADDR_HOURS 0x02 +#define RX8900_REGADDR_DAY 0x03 +#define RX8900_REGADDR_DATE 0x04 +#define RX8900_REGADDR_MONTH 0x05 +#define RX8900_REGADDR_YEAR 0x06 +#define RX8900_REGADDR_RAM 0x07 +#define RX8900_REGADDR_ALARMMIN 0x08 +#define RX8900_REGADDR_ALARMHOUR 0x09 +#define RX8900_REGADDR_ALARMDAY 0x0A +#define RX8900_REGADDR_ALARMWEEK 0x0A +#define RX8900_REGADDR_TIMECOUNTER_0 0x0B +#define RX8900_REGADDR_TIMECOUNTER_1 0x0C +#define RX8900_REGADDR_EXTENSIONREG 0x0D +#define RX8900_REGADDR_FLAGREG 0x0E +#define RX8900_REGADDR_CONTRLREG 0xF +#define RX8900_REGADDR_BACKUP_FUN 0x18 + +#define RX8900_VDETOFF_SWOFF 0x0C +#define TEMPERATURE_COMPENSATION_2S 0x40 +#define OUTPUT_FREQUENCY_32768 0x0C +#define FLAG_REG_DEFAULT 0x00 +#define RX8900_RAM_REG_DEFAULT 0x5A + + +#define RTC_DELAY_1000_MACROSECOND 1000 +#define EFI_TIMEOFFSET_TIMEZONE 0x5A0 + +#endif diff --git a/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c new file mode 100644 index 0000000..bb124fd --- /dev/null +++ b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c @@ -0,0 +1,468 @@ +/** @file + + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Uefi.h> +#include <PiDxe.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/I2CLib.h> +#include <Library/RtcHelperLib.h> +#include <Library/TimeBaseLib.h> +#include <Library/TimerLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Protocol/RealTimeClock.h> +#include "RX8900RealTimeClock.h" + +extern I2C_DEVICE gRtcDevice; + +STATIC BOOLEAN mRX8900Initialized = FALSE; +STATIC CONST CHAR16 mTimeZoneVariableName[] = L"RX8900RtcTimeZone"; +STATIC CONST CHAR16 mDaylightVariableName[] = L"RX8900RtcDaylight"; + +EFI_STATUS +InitializeRX8900 ( + VOID + ) +{ + EFI_STATUS Status; + unsigned char writeTemp; + + Status = SwitchRtcI2cChannelAndLock (); + if (EFI_ERROR (Status)) { + goto EXIT; + } + + Status = I2CInit (gRtcDevice.Socket, gRtcDevice.Port, Normal); + if (EFI_ERROR (Status)) { + goto EXIT; + } + + writeTemp = RX8900_VDETOFF_SWOFF; + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_BACKUP_FUN, 1, &writeTemp); + if (EFI_ERROR (Status)) { + goto EXIT; + } + writeTemp = TEMPERATURE_COMPENSATION_2S; + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_CONTRLREG, 1, &writeTemp); + if (EFI_ERROR (Status)) { + goto EXIT; + } + writeTemp = OUTPUT_FREQUENCY_32768; + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_EXTENSIONREG, 1, &writeTemp); + if (EFI_ERROR (Status)) { + goto EXIT; + } + + writeTemp = FLAG_REG_DEFAULT; + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_FLAGREG, 1, &writeTemp); + if (EFI_ERROR (Status)) { + goto EXIT; + } + writeTemp = RX8900_RAM_REG_DEFAULT; + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_RAM, 1, &writeTemp); + if (EFI_ERROR (Status)) { + goto EXIT; + } + + mRX8900Initialized = TRUE; + + EXIT: + + ReleaseOwnershipOfRtc (); + return Status; +} + +STATIC +INT16 +GetTimeZone ( + VOID + ) +{ + EFI_STATUS Status; + INT16 TimeZone; + UINTN Size; + + TimeZone = EFI_UNSPECIFIED_TIMEZONE; + Size = sizeof (TimeZone); + Status = EfiGetVariable ( + (CHAR16 *)mTimeZoneVariableName, + &gEfiCallerIdGuid, + NULL, + &Size, + (VOID *)&TimeZone + ); + + if (EFI_ERROR (Status)) { + TimeZone = EFI_UNSPECIFIED_TIMEZONE; + // The time zone variable does not exist in non-volatile storage, so create it. + Status = EfiSetVariable ( + (CHAR16 *)mTimeZoneVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + Size, + (VOID *)&TimeZone + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Failed to save %s variable, Status = %r\n", + mTimeZoneVariableName, Status)); + } + } else { + // Check TimeZone bounds: -1440 to 1440 or 2047 + if ((TimeZone < -EFI_TIMEOFFSET_TIMEZONE) || (TimeZone > EFI_TIMEOFFSET_TIMEZONE)) { + TimeZone = EFI_UNSPECIFIED_TIMEZONE; + } + } + + return TimeZone; +} + +STATIC +UINT8 +GetDayLight ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 DayLight; + UINTN Size; + + DayLight = 0; + // Get the current daylight information from non-volatile storage + Size = sizeof (DayLight); + Status = EfiGetVariable ( + (CHAR16 *)mDaylightVariableName, + &gEfiCallerIdGuid, + NULL, + &Size, + (VOID *)&DayLight + ); + + if (EFI_ERROR (Status)) { + DayLight = 0; + // The daylight variable does not exist in non-volatile storage, so create it. + Status = EfiSetVariable ( + (CHAR16 *)mDaylightVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + Size, + (VOID *)&DayLight + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Failed to save %s variable, Status = %r\n", + mDaylightVariableName, Status)); + } + } + + return DayLight; +} + +EFI_STATUS +EFIAPI +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +{ + EFI_STATUS Status; + UINT8 Temp[7] = {0}; + UINT16 BaseYear = 2000; + UINTN EpochSeconds; + UINT8 TryCount = 0; + + // Ensure Time is a valid pointer + if (Time == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Initialize the hardware if not already done + if (!mRX8900Initialized) { + Status = InitializeRX8900 (); + if (EFI_ERROR (Status)) { + return EFI_NOT_READY; + } + } + + Status = SwitchRtcI2cChannelAndLock (); + if (EFI_ERROR (Status)) { + ReleaseOwnershipOfRtc (); + return Status; + } + + do { + Status = I2CRead (&gRtcDevice, RX8900_REGADDR_SECONDS, 7, Temp); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Err; + } + + Time->Second = BcdToDecimal8 (Temp[0]); + Time->Minute = BcdToDecimal8 (Temp[1]); + Time->Hour = BcdToDecimal8 (Temp[2]); + Time->Day = BcdToDecimal8 (Temp[4]); + Time->Month = BcdToDecimal8 (Temp[5]); + Time->Year = BaseYear + BcdToDecimal8 (Temp[6]); + Time->Nanosecond = 0; + + EpochSeconds = EfiTimeToEpoch (Time); + + Time->TimeZone = GetTimeZone (); + // Adjust for the correct time zone + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { + EpochSeconds += Time->TimeZone * SEC_PER_MIN; + } + + Time->Daylight = GetDayLight (); + // 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; + } + + // Convert from internal 32-bit time to UEFI time + EpochToEfiTime (EpochSeconds, Time); + if ((!IsTimeValid (Time)) || ((Time->Year - BaseYear) > 99) || (Time->Year < 2000)) { + DEBUG ((DEBUG_INFO, "LibGetTime: %d-%d-%d %d-%d-%d EpochSeconds:%llx is invalid time!\n", + Time->Second, Time->Minute, Time->Hour, Time->Day, Time->Month, + Time->Year, EpochSeconds)); + Status = EFI_DEVICE_ERROR; + } + +Err: + TryCount++; + } while ((TryCount < 3) && (EFI_ERROR (Status))); + + ReleaseOwnershipOfRtc (); + return Status; +} + +STATIC +EFI_STATUS +SetTimeToRX8900 ( + IN EFI_TIME *Time + ) +{ + EFI_STATUS Status; + UINT8 Temp; + + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); + Temp = DecimalToBcd8 (Time->Second); + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_SECONDS, 1, &Temp); + if(EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + return Status; + } + + Temp = DecimalToBcd8 (Time->Minute); + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_MIUTES, 1, &Temp); + if(EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + return Status; + } + + Temp = DecimalToBcd8 (Time->Hour); + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_HOURS, 1, &Temp); + if(EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + return Status; + } + + Temp = DecimalToBcd8 (Time->Day); + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_DATE, 1, &Temp); + if(EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + return Status; + } + + Temp = DecimalToBcd8 (Time->Month); + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_MONTH, 1, &Temp); + if(EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + return Status; + } + + Time->Year= Time->Year % 100; + Temp = Time->Year; + Temp = DecimalToBcd8 (Temp); + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_YEAR, 1, &Temp); + if(EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + return Status; + } + + return Status; +} + +EFI_STATUS +EFIAPI +LibSetTime ( + IN EFI_TIME *Time + ) +{ + EFI_STATUS Status; + UINTN EpochSeconds; + + // Initialize the hardware if not already done + if (!mRX8900Initialized) { + Status = InitializeRX8900 (); + if (EFI_ERROR (Status)) { + goto EXIT; + } + } + + Status = SwitchRtcI2cChannelAndLock (); + if (EFI_ERROR (Status)) { + goto EXIT; + } + + if(!IsTimeValid(Time)){ + return EFI_INVALID_PARAMETER; + } + + 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 + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { + // Convert to un-adjusted time, i.e. fall back one hour + EpochSeconds -= SEC_PER_HOUR; + } + + EpochToEfiTime (EpochSeconds, Time); + Status = SetTimeToRX8900 (Time); + if (EFI_ERROR (Status)) { + goto EXIT; + } + + // Save the current time zone information into non-volatile storage + Status = EfiSetVariable ( + (CHAR16 *)mTimeZoneVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (Time->TimeZone), + (VOID *)&(Time->TimeZone) + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "LibSetTime: Failed to save %s variable, Status = %r\n", + mTimeZoneVariableName, Status)); + goto EXIT; + } + + // Save the current daylight information into non-volatile storage + Status = EfiSetVariable ( + (CHAR16 *)mDaylightVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(Time->Daylight), + (VOID *)&(Time->Daylight) + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "LibSetTime: Failed to save %s variable, Status = %r\n", + mDaylightVariableName, Status)); + goto EXIT; + } + + EXIT: + ReleaseOwnershipOfRtc (); + return Status; +} + +EFI_STATUS +EFIAPI +LibGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ) +{ + // Not a required feature + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +LibRtcInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_TIME EfiTime; + + // Setup the setters and getters + gRT->GetTime = LibGetTime; + gRT->SetTime = LibSetTime; + gRT->GetWakeupTime = LibGetWakeupTime; + gRT->SetWakeupTime = LibSetWakeupTime; + + Status = gRT->GetTime (&EfiTime, NULL); + if (EFI_ERROR (Status) || (EfiTime.Year < 2000) || (EfiTime.Year > 2099) || + (!IsTimeValid (&EfiTime))) { + EfiTime.Year = 2000; + EfiTime.Month = 1; + EfiTime.Day = 1; + EfiTime.Hour = 0; + EfiTime.Minute = 0; + EfiTime.Second = 0; + EfiTime.Nanosecond = 0; + EfiTime.Daylight = 0; + EfiTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE; + + Status = gRT->SetTime (&EfiTime); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SetTime Status : %r\n", Status)); + } + } + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiRealTimeClockArchProtocolGuid, + NULL, + NULL + ); + + return Status; +} + + +VOID +EFIAPI +LibRtcVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + return; +} diff --git a/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf new file mode 100644 index 0000000..aa07a06 --- /dev/null +++ b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf @@ -0,0 +1,33 @@ +/** @file + + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = RX8900RealTimeClockLib + FILE_GUID = 55BBD010-EA76-4836-8FEA-99CBAA6664F4 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RealTimeClockLib + +[Sources.common] + RX8900RealTimeClockLib.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + DebugLib + I2CLib + IoLib + RtcHelperLib + TimeBaseLib + TimerLib + UefiLib + UefiRuntimeLib -- 2.8.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC edk2-platforms v1 2/2] Silicon/Hisilicon: Add RX8900RealTimeClockLib 2020-05-18 13:37 ` [RFC edk2-platforms v1 2/2] Silicon/Hisilicon: Add RX8900RealTimeClockLib Ming Huang @ 2020-05-18 18:13 ` Leif Lindholm 2020-05-19 10:30 ` Ming Huang 0 siblings, 1 reply; 7+ messages in thread From: Leif Lindholm @ 2020-05-18 18:13 UTC (permalink / raw) To: Ming Huang Cc: devel, ard.biesheuvel, lidongzhan, songdongkuang, wanghuiqiang, qiuliangen On Mon, May 18, 2020 at 21:37:24 +0800, Ming Huang wrote: > There are some boards base on D06, but use RX8900 RTC, > so upstream the RX8900RealTimeClockLib. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Ming Huang <huangming23@huawei.com> > --- > Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h | 41 ++ > Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c | 468 ++++++++++++++++++++ > Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf | 33 ++ > 3 files changed, 542 insertions(+) > > diff --git a/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h > new file mode 100644 > index 0000000..6bcef10 > --- /dev/null > +++ b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h > @@ -0,0 +1,41 @@ > +/** @file > + > + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef __RX8900_REAL_TIME_CLOCK_H__ > +#define __RX8900_REAL_TIME_CLOCK_H__ Please drop leading __. > + > +#define RX8900_REGADDR_SECONDS 0x00 > +#define RX8900_REGADDR_MIUTES 0x01 > +#define RX8900_REGADDR_HOURS 0x02 > +#define RX8900_REGADDR_DAY 0x03 > +#define RX8900_REGADDR_DATE 0x04 > +#define RX8900_REGADDR_MONTH 0x05 > +#define RX8900_REGADDR_YEAR 0x06 > +#define RX8900_REGADDR_RAM 0x07 > +#define RX8900_REGADDR_ALARMMIN 0x08 > +#define RX8900_REGADDR_ALARMHOUR 0x09 > +#define RX8900_REGADDR_ALARMDAY 0x0A > +#define RX8900_REGADDR_ALARMWEEK 0x0A > +#define RX8900_REGADDR_TIMECOUNTER_0 0x0B > +#define RX8900_REGADDR_TIMECOUNTER_1 0x0C > +#define RX8900_REGADDR_EXTENSIONREG 0x0D > +#define RX8900_REGADDR_FLAGREG 0x0E > +#define RX8900_REGADDR_CONTRLREG 0xF > +#define RX8900_REGADDR_BACKUP_FUN 0x18 > + > +#define RX8900_VDETOFF_SWOFF 0x0C > +#define TEMPERATURE_COMPENSATION_2S 0x40 > +#define OUTPUT_FREQUENCY_32768 0x0C > +#define FLAG_REG_DEFAULT 0x00 > +#define RX8900_RAM_REG_DEFAULT 0x5A > + > + > +#define RTC_DELAY_1000_MACROSECOND 1000 Please keep this definition in RtcHelperLib.h. / Leif > +#define EFI_TIMEOFFSET_TIMEZONE 0x5A0 > + > +#endif > diff --git a/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c > new file mode 100644 > index 0000000..bb124fd > --- /dev/null > +++ b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c > @@ -0,0 +1,468 @@ > +/** @file > + > + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <Uefi.h> > +#include <PiDxe.h> > +#include <Library/BaseLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/DebugLib.h> > +#include <Library/I2CLib.h> > +#include <Library/RtcHelperLib.h> > +#include <Library/TimeBaseLib.h> > +#include <Library/TimerLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiLib.h> > +#include <Library/UefiRuntimeLib.h> > +#include <Library/UefiRuntimeServicesTableLib.h> > +#include <Protocol/RealTimeClock.h> > +#include "RX8900RealTimeClock.h" > + > +extern I2C_DEVICE gRtcDevice; > + > +STATIC BOOLEAN mRX8900Initialized = FALSE; > +STATIC CONST CHAR16 mTimeZoneVariableName[] = L"RX8900RtcTimeZone"; > +STATIC CONST CHAR16 mDaylightVariableName[] = L"RX8900RtcDaylight"; > + > +EFI_STATUS > +InitializeRX8900 ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + unsigned char writeTemp; > + > + Status = SwitchRtcI2cChannelAndLock (); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + > + Status = I2CInit (gRtcDevice.Socket, gRtcDevice.Port, Normal); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + > + writeTemp = RX8900_VDETOFF_SWOFF; > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_BACKUP_FUN, 1, &writeTemp); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + writeTemp = TEMPERATURE_COMPENSATION_2S; > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_CONTRLREG, 1, &writeTemp); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + writeTemp = OUTPUT_FREQUENCY_32768; > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_EXTENSIONREG, 1, &writeTemp); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + > + writeTemp = FLAG_REG_DEFAULT; > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_FLAGREG, 1, &writeTemp); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + writeTemp = RX8900_RAM_REG_DEFAULT; > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_RAM, 1, &writeTemp); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + > + mRX8900Initialized = TRUE; > + > + EXIT: > + > + ReleaseOwnershipOfRtc (); > + return Status; > +} > + > +STATIC > +INT16 > +GetTimeZone ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + INT16 TimeZone; > + UINTN Size; > + > + TimeZone = EFI_UNSPECIFIED_TIMEZONE; > + Size = sizeof (TimeZone); > + Status = EfiGetVariable ( > + (CHAR16 *)mTimeZoneVariableName, > + &gEfiCallerIdGuid, > + NULL, > + &Size, > + (VOID *)&TimeZone > + ); > + > + if (EFI_ERROR (Status)) { > + TimeZone = EFI_UNSPECIFIED_TIMEZONE; > + // The time zone variable does not exist in non-volatile storage, so create it. > + Status = EfiSetVariable ( > + (CHAR16 *)mTimeZoneVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + Size, > + (VOID *)&TimeZone > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, "Failed to save %s variable, Status = %r\n", > + mTimeZoneVariableName, Status)); > + } > + } else { > + // Check TimeZone bounds: -1440 to 1440 or 2047 > + if ((TimeZone < -EFI_TIMEOFFSET_TIMEZONE) || (TimeZone > EFI_TIMEOFFSET_TIMEZONE)) { > + TimeZone = EFI_UNSPECIFIED_TIMEZONE; > + } > + } > + > + return TimeZone; > +} > + > +STATIC > +UINT8 > +GetDayLight ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + UINT8 DayLight; > + UINTN Size; > + > + DayLight = 0; > + // Get the current daylight information from non-volatile storage > + Size = sizeof (DayLight); > + Status = EfiGetVariable ( > + (CHAR16 *)mDaylightVariableName, > + &gEfiCallerIdGuid, > + NULL, > + &Size, > + (VOID *)&DayLight > + ); > + > + if (EFI_ERROR (Status)) { > + DayLight = 0; > + // The daylight variable does not exist in non-volatile storage, so create it. > + Status = EfiSetVariable ( > + (CHAR16 *)mDaylightVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + Size, > + (VOID *)&DayLight > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, "Failed to save %s variable, Status = %r\n", > + mDaylightVariableName, Status)); > + } > + } > + > + return DayLight; > +} > + > +EFI_STATUS > +EFIAPI > +LibGetTime ( > + OUT EFI_TIME *Time, > + OUT EFI_TIME_CAPABILITIES *Capabilities > + ) > +{ > + EFI_STATUS Status; > + UINT8 Temp[7] = {0}; > + UINT16 BaseYear = 2000; > + UINTN EpochSeconds; > + UINT8 TryCount = 0; > + > + // Ensure Time is a valid pointer > + if (Time == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + // Initialize the hardware if not already done > + if (!mRX8900Initialized) { > + Status = InitializeRX8900 (); > + if (EFI_ERROR (Status)) { > + return EFI_NOT_READY; > + } > + } > + > + Status = SwitchRtcI2cChannelAndLock (); > + if (EFI_ERROR (Status)) { > + ReleaseOwnershipOfRtc (); > + return Status; > + } > + > + do { > + Status = I2CRead (&gRtcDevice, RX8900_REGADDR_SECONDS, 7, Temp); > + if (EFI_ERROR (Status)) { > + Status = EFI_DEVICE_ERROR; > + goto Err; > + } > + > + Time->Second = BcdToDecimal8 (Temp[0]); > + Time->Minute = BcdToDecimal8 (Temp[1]); > + Time->Hour = BcdToDecimal8 (Temp[2]); > + Time->Day = BcdToDecimal8 (Temp[4]); > + Time->Month = BcdToDecimal8 (Temp[5]); > + Time->Year = BaseYear + BcdToDecimal8 (Temp[6]); > + Time->Nanosecond = 0; > + > + EpochSeconds = EfiTimeToEpoch (Time); > + > + Time->TimeZone = GetTimeZone (); > + // Adjust for the correct time zone > + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { > + EpochSeconds += Time->TimeZone * SEC_PER_MIN; > + } > + > + Time->Daylight = GetDayLight (); > + // 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; > + } > + > + // Convert from internal 32-bit time to UEFI time > + EpochToEfiTime (EpochSeconds, Time); > + if ((!IsTimeValid (Time)) || ((Time->Year - BaseYear) > 99) || (Time->Year < 2000)) { > + DEBUG ((DEBUG_INFO, "LibGetTime: %d-%d-%d %d-%d-%d EpochSeconds:%llx is invalid time!\n", > + Time->Second, Time->Minute, Time->Hour, Time->Day, Time->Month, > + Time->Year, EpochSeconds)); > + Status = EFI_DEVICE_ERROR; > + } > + > +Err: > + TryCount++; > + } while ((TryCount < 3) && (EFI_ERROR (Status))); > + > + ReleaseOwnershipOfRtc (); > + return Status; > +} > + > +STATIC > +EFI_STATUS > +SetTimeToRX8900 ( > + IN EFI_TIME *Time > + ) > +{ > + EFI_STATUS Status; > + UINT8 Temp; > + > + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); > + Temp = DecimalToBcd8 (Time->Second); > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_SECONDS, 1, &Temp); > + if(EFI_ERROR (Status)) { > + Status = EFI_DEVICE_ERROR; > + return Status; > + } > + > + Temp = DecimalToBcd8 (Time->Minute); > + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_MIUTES, 1, &Temp); > + if(EFI_ERROR (Status)) { > + Status = EFI_DEVICE_ERROR; > + return Status; > + } > + > + Temp = DecimalToBcd8 (Time->Hour); > + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_HOURS, 1, &Temp); > + if(EFI_ERROR (Status)) { > + Status = EFI_DEVICE_ERROR; > + return Status; > + } > + > + Temp = DecimalToBcd8 (Time->Day); > + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_DATE, 1, &Temp); > + if(EFI_ERROR (Status)) { > + Status = EFI_DEVICE_ERROR; > + return Status; > + } > + > + Temp = DecimalToBcd8 (Time->Month); > + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_MONTH, 1, &Temp); > + if(EFI_ERROR (Status)) { > + Status = EFI_DEVICE_ERROR; > + return Status; > + } > + > + Time->Year= Time->Year % 100; > + Temp = Time->Year; > + Temp = DecimalToBcd8 (Temp); > + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); > + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_YEAR, 1, &Temp); > + if(EFI_ERROR (Status)) { > + Status = EFI_DEVICE_ERROR; > + return Status; > + } > + > + return Status; > +} > + > +EFI_STATUS > +EFIAPI > +LibSetTime ( > + IN EFI_TIME *Time > + ) > +{ > + EFI_STATUS Status; > + UINTN EpochSeconds; > + > + // Initialize the hardware if not already done > + if (!mRX8900Initialized) { > + Status = InitializeRX8900 (); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + } > + > + Status = SwitchRtcI2cChannelAndLock (); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + > + if(!IsTimeValid(Time)){ > + return EFI_INVALID_PARAMETER; > + } > + > + 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 > + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { > + // Convert to un-adjusted time, i.e. fall back one hour > + EpochSeconds -= SEC_PER_HOUR; > + } > + > + EpochToEfiTime (EpochSeconds, Time); > + Status = SetTimeToRX8900 (Time); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + > + // Save the current time zone information into non-volatile storage > + Status = EfiSetVariable ( > + (CHAR16 *)mTimeZoneVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + sizeof (Time->TimeZone), > + (VOID *)&(Time->TimeZone) > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, "LibSetTime: Failed to save %s variable, Status = %r\n", > + mTimeZoneVariableName, Status)); > + goto EXIT; > + } > + > + // Save the current daylight information into non-volatile storage > + Status = EfiSetVariable ( > + (CHAR16 *)mDaylightVariableName, > + &gEfiCallerIdGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, > + sizeof(Time->Daylight), > + (VOID *)&(Time->Daylight) > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, "LibSetTime: Failed to save %s variable, Status = %r\n", > + mDaylightVariableName, Status)); > + goto EXIT; > + } > + > + EXIT: > + ReleaseOwnershipOfRtc (); > + return Status; > +} > + > +EFI_STATUS > +EFIAPI > +LibGetWakeupTime ( > + OUT BOOLEAN *Enabled, > + OUT BOOLEAN *Pending, > + OUT EFI_TIME *Time > + ) > +{ > + // Not a required feature > + return EFI_UNSUPPORTED; > +} > + > +EFI_STATUS > +EFIAPI > +LibSetWakeupTime ( > + IN BOOLEAN Enabled, > + OUT EFI_TIME *Time > + ) > +{ > + // Not a required feature > + return EFI_UNSUPPORTED; > +} > + > + > +EFI_STATUS > +EFIAPI > +LibRtcInitialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE Handle; > + EFI_TIME EfiTime; > + > + // Setup the setters and getters > + gRT->GetTime = LibGetTime; > + gRT->SetTime = LibSetTime; > + gRT->GetWakeupTime = LibGetWakeupTime; > + gRT->SetWakeupTime = LibSetWakeupTime; > + > + Status = gRT->GetTime (&EfiTime, NULL); > + if (EFI_ERROR (Status) || (EfiTime.Year < 2000) || (EfiTime.Year > 2099) || > + (!IsTimeValid (&EfiTime))) { > + EfiTime.Year = 2000; > + EfiTime.Month = 1; > + EfiTime.Day = 1; > + EfiTime.Hour = 0; > + EfiTime.Minute = 0; > + EfiTime.Second = 0; > + EfiTime.Nanosecond = 0; > + EfiTime.Daylight = 0; > + EfiTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE; > + > + Status = gRT->SetTime (&EfiTime); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "SetTime Status : %r\n", Status)); > + } > + } > + > + Handle = NULL; > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &Handle, > + &gEfiRealTimeClockArchProtocolGuid, > + NULL, > + NULL > + ); > + > + return Status; > +} > + > + > +VOID > +EFIAPI > +LibRtcVirtualNotifyEvent ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + return; > +} > diff --git a/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf > new file mode 100644 > index 0000000..aa07a06 > --- /dev/null > +++ b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf > @@ -0,0 +1,33 @@ > +/** @file > + > + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +[Defines] > + INF_VERSION = 0x0001001A > + BASE_NAME = RX8900RealTimeClockLib > + FILE_GUID = 55BBD010-EA76-4836-8FEA-99CBAA6664F4 > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = RealTimeClockLib > + > +[Sources.common] > + RX8900RealTimeClockLib.c > + > +[Packages] > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + Silicon/Hisilicon/HisiPkg.dec > + > +[LibraryClasses] > + DebugLib > + I2CLib > + IoLib > + RtcHelperLib > + TimeBaseLib > + TimerLib > + UefiLib > + UefiRuntimeLib > -- > 2.8.1 > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC edk2-platforms v1 2/2] Silicon/Hisilicon: Add RX8900RealTimeClockLib 2020-05-18 18:13 ` Leif Lindholm @ 2020-05-19 10:30 ` Ming Huang 0 siblings, 0 replies; 7+ messages in thread From: Ming Huang @ 2020-05-19 10:30 UTC (permalink / raw) To: Leif Lindholm Cc: devel, ard.biesheuvel, lidongzhan, songdongkuang, wanghuiqiang, qiuliangen 在 2020/5/19 2:13, Leif Lindholm 写道: > On Mon, May 18, 2020 at 21:37:24 +0800, Ming Huang wrote: >> There are some boards base on D06, but use RX8900 RTC, >> so upstream the RX8900RealTimeClockLib. >> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Ming Huang <huangming23@huawei.com> >> --- >> Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h | 41 ++ >> Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c | 468 ++++++++++++++++++++ >> Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf | 33 ++ >> 3 files changed, 542 insertions(+) >> >> diff --git a/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h >> new file mode 100644 >> index 0000000..6bcef10 >> --- /dev/null >> +++ b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClock.h >> @@ -0,0 +1,41 @@ >> +/** @file >> + >> + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> >> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#ifndef __RX8900_REAL_TIME_CLOCK_H__ >> +#define __RX8900_REAL_TIME_CLOCK_H__ > > Please drop leading __. Ok. > >> + >> +#define RX8900_REGADDR_SECONDS 0x00 >> +#define RX8900_REGADDR_MIUTES 0x01 >> +#define RX8900_REGADDR_HOURS 0x02 >> +#define RX8900_REGADDR_DAY 0x03 >> +#define RX8900_REGADDR_DATE 0x04 >> +#define RX8900_REGADDR_MONTH 0x05 >> +#define RX8900_REGADDR_YEAR 0x06 >> +#define RX8900_REGADDR_RAM 0x07 >> +#define RX8900_REGADDR_ALARMMIN 0x08 >> +#define RX8900_REGADDR_ALARMHOUR 0x09 >> +#define RX8900_REGADDR_ALARMDAY 0x0A >> +#define RX8900_REGADDR_ALARMWEEK 0x0A >> +#define RX8900_REGADDR_TIMECOUNTER_0 0x0B >> +#define RX8900_REGADDR_TIMECOUNTER_1 0x0C >> +#define RX8900_REGADDR_EXTENSIONREG 0x0D >> +#define RX8900_REGADDR_FLAGREG 0x0E >> +#define RX8900_REGADDR_CONTRLREG 0xF >> +#define RX8900_REGADDR_BACKUP_FUN 0x18 >> + >> +#define RX8900_VDETOFF_SWOFF 0x0C >> +#define TEMPERATURE_COMPENSATION_2S 0x40 >> +#define OUTPUT_FREQUENCY_32768 0x0C >> +#define FLAG_REG_DEFAULT 0x00 >> +#define RX8900_RAM_REG_DEFAULT 0x5A >> + >> + >> +#define RTC_DELAY_1000_MACROSECOND 1000 > > Please keep this definition in RtcHelperLib.h. Ok, Modify in v2. Thanks, Ming > > / > Leif > >> +#define EFI_TIMEOFFSET_TIMEZONE 0x5A0 >> + >> +#endif >> diff --git a/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c >> new file mode 100644 >> index 0000000..bb124fd >> --- /dev/null >> +++ b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.c >> @@ -0,0 +1,468 @@ >> +/** @file >> + >> + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> >> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#include <Uefi.h> >> +#include <PiDxe.h> >> +#include <Library/BaseLib.h> >> +#include <Library/BaseMemoryLib.h> >> +#include <Library/DebugLib.h> >> +#include <Library/I2CLib.h> >> +#include <Library/RtcHelperLib.h> >> +#include <Library/TimeBaseLib.h> >> +#include <Library/TimerLib.h> >> +#include <Library/UefiBootServicesTableLib.h> >> +#include <Library/UefiLib.h> >> +#include <Library/UefiRuntimeLib.h> >> +#include <Library/UefiRuntimeServicesTableLib.h> >> +#include <Protocol/RealTimeClock.h> >> +#include "RX8900RealTimeClock.h" >> + >> +extern I2C_DEVICE gRtcDevice; >> + >> +STATIC BOOLEAN mRX8900Initialized = FALSE; >> +STATIC CONST CHAR16 mTimeZoneVariableName[] = L"RX8900RtcTimeZone"; >> +STATIC CONST CHAR16 mDaylightVariableName[] = L"RX8900RtcDaylight"; >> + >> +EFI_STATUS >> +InitializeRX8900 ( >> + VOID >> + ) >> +{ >> + EFI_STATUS Status; >> + unsigned char writeTemp; >> + >> + Status = SwitchRtcI2cChannelAndLock (); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + >> + Status = I2CInit (gRtcDevice.Socket, gRtcDevice.Port, Normal); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + >> + writeTemp = RX8900_VDETOFF_SWOFF; >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_BACKUP_FUN, 1, &writeTemp); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + writeTemp = TEMPERATURE_COMPENSATION_2S; >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_CONTRLREG, 1, &writeTemp); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + writeTemp = OUTPUT_FREQUENCY_32768; >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_EXTENSIONREG, 1, &writeTemp); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + >> + writeTemp = FLAG_REG_DEFAULT; >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_FLAGREG, 1, &writeTemp); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + writeTemp = RX8900_RAM_REG_DEFAULT; >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_RAM, 1, &writeTemp); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + >> + mRX8900Initialized = TRUE; >> + >> + EXIT: >> + >> + ReleaseOwnershipOfRtc (); >> + return Status; >> +} >> + >> +STATIC >> +INT16 >> +GetTimeZone ( >> + VOID >> + ) >> +{ >> + EFI_STATUS Status; >> + INT16 TimeZone; >> + UINTN Size; >> + >> + TimeZone = EFI_UNSPECIFIED_TIMEZONE; >> + Size = sizeof (TimeZone); >> + Status = EfiGetVariable ( >> + (CHAR16 *)mTimeZoneVariableName, >> + &gEfiCallerIdGuid, >> + NULL, >> + &Size, >> + (VOID *)&TimeZone >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + TimeZone = EFI_UNSPECIFIED_TIMEZONE; >> + // The time zone variable does not exist in non-volatile storage, so create it. >> + Status = EfiSetVariable ( >> + (CHAR16 *)mTimeZoneVariableName, >> + &gEfiCallerIdGuid, >> + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, >> + Size, >> + (VOID *)&TimeZone >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_INFO, "Failed to save %s variable, Status = %r\n", >> + mTimeZoneVariableName, Status)); >> + } >> + } else { >> + // Check TimeZone bounds: -1440 to 1440 or 2047 >> + if ((TimeZone < -EFI_TIMEOFFSET_TIMEZONE) || (TimeZone > EFI_TIMEOFFSET_TIMEZONE)) { >> + TimeZone = EFI_UNSPECIFIED_TIMEZONE; >> + } >> + } >> + >> + return TimeZone; >> +} >> + >> +STATIC >> +UINT8 >> +GetDayLight ( >> + VOID >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT8 DayLight; >> + UINTN Size; >> + >> + DayLight = 0; >> + // Get the current daylight information from non-volatile storage >> + Size = sizeof (DayLight); >> + Status = EfiGetVariable ( >> + (CHAR16 *)mDaylightVariableName, >> + &gEfiCallerIdGuid, >> + NULL, >> + &Size, >> + (VOID *)&DayLight >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + DayLight = 0; >> + // The daylight variable does not exist in non-volatile storage, so create it. >> + Status = EfiSetVariable ( >> + (CHAR16 *)mDaylightVariableName, >> + &gEfiCallerIdGuid, >> + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, >> + Size, >> + (VOID *)&DayLight >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_INFO, "Failed to save %s variable, Status = %r\n", >> + mDaylightVariableName, Status)); >> + } >> + } >> + >> + return DayLight; >> +} >> + >> +EFI_STATUS >> +EFIAPI >> +LibGetTime ( >> + OUT EFI_TIME *Time, >> + OUT EFI_TIME_CAPABILITIES *Capabilities >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT8 Temp[7] = {0}; >> + UINT16 BaseYear = 2000; >> + UINTN EpochSeconds; >> + UINT8 TryCount = 0; >> + >> + // Ensure Time is a valid pointer >> + if (Time == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + // Initialize the hardware if not already done >> + if (!mRX8900Initialized) { >> + Status = InitializeRX8900 (); >> + if (EFI_ERROR (Status)) { >> + return EFI_NOT_READY; >> + } >> + } >> + >> + Status = SwitchRtcI2cChannelAndLock (); >> + if (EFI_ERROR (Status)) { >> + ReleaseOwnershipOfRtc (); >> + return Status; >> + } >> + >> + do { >> + Status = I2CRead (&gRtcDevice, RX8900_REGADDR_SECONDS, 7, Temp); >> + if (EFI_ERROR (Status)) { >> + Status = EFI_DEVICE_ERROR; >> + goto Err; >> + } >> + >> + Time->Second = BcdToDecimal8 (Temp[0]); >> + Time->Minute = BcdToDecimal8 (Temp[1]); >> + Time->Hour = BcdToDecimal8 (Temp[2]); >> + Time->Day = BcdToDecimal8 (Temp[4]); >> + Time->Month = BcdToDecimal8 (Temp[5]); >> + Time->Year = BaseYear + BcdToDecimal8 (Temp[6]); >> + Time->Nanosecond = 0; >> + >> + EpochSeconds = EfiTimeToEpoch (Time); >> + >> + Time->TimeZone = GetTimeZone (); >> + // Adjust for the correct time zone >> + if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) { >> + EpochSeconds += Time->TimeZone * SEC_PER_MIN; >> + } >> + >> + Time->Daylight = GetDayLight (); >> + // 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; >> + } >> + >> + // Convert from internal 32-bit time to UEFI time >> + EpochToEfiTime (EpochSeconds, Time); >> + if ((!IsTimeValid (Time)) || ((Time->Year - BaseYear) > 99) || (Time->Year < 2000)) { >> + DEBUG ((DEBUG_INFO, "LibGetTime: %d-%d-%d %d-%d-%d EpochSeconds:%llx is invalid time!\n", >> + Time->Second, Time->Minute, Time->Hour, Time->Day, Time->Month, >> + Time->Year, EpochSeconds)); >> + Status = EFI_DEVICE_ERROR; >> + } >> + >> +Err: >> + TryCount++; >> + } while ((TryCount < 3) && (EFI_ERROR (Status))); >> + >> + ReleaseOwnershipOfRtc (); >> + return Status; >> +} >> + >> +STATIC >> +EFI_STATUS >> +SetTimeToRX8900 ( >> + IN EFI_TIME *Time >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT8 Temp; >> + >> + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); >> + Temp = DecimalToBcd8 (Time->Second); >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_SECONDS, 1, &Temp); >> + if(EFI_ERROR (Status)) { >> + Status = EFI_DEVICE_ERROR; >> + return Status; >> + } >> + >> + Temp = DecimalToBcd8 (Time->Minute); >> + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_MIUTES, 1, &Temp); >> + if(EFI_ERROR (Status)) { >> + Status = EFI_DEVICE_ERROR; >> + return Status; >> + } >> + >> + Temp = DecimalToBcd8 (Time->Hour); >> + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_HOURS, 1, &Temp); >> + if(EFI_ERROR (Status)) { >> + Status = EFI_DEVICE_ERROR; >> + return Status; >> + } >> + >> + Temp = DecimalToBcd8 (Time->Day); >> + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_DATE, 1, &Temp); >> + if(EFI_ERROR (Status)) { >> + Status = EFI_DEVICE_ERROR; >> + return Status; >> + } >> + >> + Temp = DecimalToBcd8 (Time->Month); >> + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_MONTH, 1, &Temp); >> + if(EFI_ERROR (Status)) { >> + Status = EFI_DEVICE_ERROR; >> + return Status; >> + } >> + >> + Time->Year= Time->Year % 100; >> + Temp = Time->Year; >> + Temp = DecimalToBcd8 (Temp); >> + (VOID)MicroSecondDelay (RTC_DELAY_1000_MACROSECOND); >> + Status = I2CWrite (&gRtcDevice, RX8900_REGADDR_YEAR, 1, &Temp); >> + if(EFI_ERROR (Status)) { >> + Status = EFI_DEVICE_ERROR; >> + return Status; >> + } >> + >> + return Status; >> +} >> + >> +EFI_STATUS >> +EFIAPI >> +LibSetTime ( >> + IN EFI_TIME *Time >> + ) >> +{ >> + EFI_STATUS Status; >> + UINTN EpochSeconds; >> + >> + // Initialize the hardware if not already done >> + if (!mRX8900Initialized) { >> + Status = InitializeRX8900 (); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + } >> + >> + Status = SwitchRtcI2cChannelAndLock (); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + >> + if(!IsTimeValid(Time)){ >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + 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 >> + if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) { >> + // Convert to un-adjusted time, i.e. fall back one hour >> + EpochSeconds -= SEC_PER_HOUR; >> + } >> + >> + EpochToEfiTime (EpochSeconds, Time); >> + Status = SetTimeToRX8900 (Time); >> + if (EFI_ERROR (Status)) { >> + goto EXIT; >> + } >> + >> + // Save the current time zone information into non-volatile storage >> + Status = EfiSetVariable ( >> + (CHAR16 *)mTimeZoneVariableName, >> + &gEfiCallerIdGuid, >> + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, >> + sizeof (Time->TimeZone), >> + (VOID *)&(Time->TimeZone) >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_INFO, "LibSetTime: Failed to save %s variable, Status = %r\n", >> + mTimeZoneVariableName, Status)); >> + goto EXIT; >> + } >> + >> + // Save the current daylight information into non-volatile storage >> + Status = EfiSetVariable ( >> + (CHAR16 *)mDaylightVariableName, >> + &gEfiCallerIdGuid, >> + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, >> + sizeof(Time->Daylight), >> + (VOID *)&(Time->Daylight) >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_INFO, "LibSetTime: Failed to save %s variable, Status = %r\n", >> + mDaylightVariableName, Status)); >> + goto EXIT; >> + } >> + >> + EXIT: >> + ReleaseOwnershipOfRtc (); >> + return Status; >> +} >> + >> +EFI_STATUS >> +EFIAPI >> +LibGetWakeupTime ( >> + OUT BOOLEAN *Enabled, >> + OUT BOOLEAN *Pending, >> + OUT EFI_TIME *Time >> + ) >> +{ >> + // Not a required feature >> + return EFI_UNSUPPORTED; >> +} >> + >> +EFI_STATUS >> +EFIAPI >> +LibSetWakeupTime ( >> + IN BOOLEAN Enabled, >> + OUT EFI_TIME *Time >> + ) >> +{ >> + // Not a required feature >> + return EFI_UNSUPPORTED; >> +} >> + >> + >> +EFI_STATUS >> +EFIAPI >> +LibRtcInitialize ( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_HANDLE Handle; >> + EFI_TIME EfiTime; >> + >> + // Setup the setters and getters >> + gRT->GetTime = LibGetTime; >> + gRT->SetTime = LibSetTime; >> + gRT->GetWakeupTime = LibGetWakeupTime; >> + gRT->SetWakeupTime = LibSetWakeupTime; >> + >> + Status = gRT->GetTime (&EfiTime, NULL); >> + if (EFI_ERROR (Status) || (EfiTime.Year < 2000) || (EfiTime.Year > 2099) || >> + (!IsTimeValid (&EfiTime))) { >> + EfiTime.Year = 2000; >> + EfiTime.Month = 1; >> + EfiTime.Day = 1; >> + EfiTime.Hour = 0; >> + EfiTime.Minute = 0; >> + EfiTime.Second = 0; >> + EfiTime.Nanosecond = 0; >> + EfiTime.Daylight = 0; >> + EfiTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE; >> + >> + Status = gRT->SetTime (&EfiTime); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "SetTime Status : %r\n", Status)); >> + } >> + } >> + >> + Handle = NULL; >> + Status = gBS->InstallMultipleProtocolInterfaces ( >> + &Handle, >> + &gEfiRealTimeClockArchProtocolGuid, >> + NULL, >> + NULL >> + ); >> + >> + return Status; >> +} >> + >> + >> +VOID >> +EFIAPI >> +LibRtcVirtualNotifyEvent ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + return; >> +} >> diff --git a/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf >> new file mode 100644 >> index 0000000..aa07a06 >> --- /dev/null >> +++ b/Silicon/Hisilicon/Library/RX8900RealTimeClockLib/RX8900RealTimeClockLib.inf >> @@ -0,0 +1,33 @@ >> +/** @file >> + >> + Copyright (c) 2020, Hisilicon Limited. All rights reserved.<BR> >> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +[Defines] >> + INF_VERSION = 0x0001001A >> + BASE_NAME = RX8900RealTimeClockLib >> + FILE_GUID = 55BBD010-EA76-4836-8FEA-99CBAA6664F4 >> + MODULE_TYPE = BASE >> + VERSION_STRING = 1.0 >> + LIBRARY_CLASS = RealTimeClockLib >> + >> +[Sources.common] >> + RX8900RealTimeClockLib.c >> + >> +[Packages] >> + EmbeddedPkg/EmbeddedPkg.dec >> + MdePkg/MdePkg.dec >> + Silicon/Hisilicon/HisiPkg.dec >> + >> +[LibraryClasses] >> + DebugLib >> + I2CLib >> + IoLib >> + RtcHelperLib >> + TimeBaseLib >> + TimerLib >> + UefiLib >> + UefiRuntimeLib >> -- >> 2.8.1 >> > > . > ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-05-19 10:30 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-05-18 13:37 [RFC edk2-platforms v1 0/2] Improve D0x Ming Huang 2020-05-18 13:37 ` [RFC edk2-platforms v1 1/2] Hisilicon/Library: Move two functions to RtcHelperLib Ming Huang 2020-05-18 18:03 ` Leif Lindholm 2020-05-19 10:28 ` Ming Huang 2020-05-18 13:37 ` [RFC edk2-platforms v1 2/2] Silicon/Hisilicon: Add RX8900RealTimeClockLib Ming Huang 2020-05-18 18:13 ` Leif Lindholm 2020-05-19 10:30 ` Ming Huang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox