The generic watchdog offset register is 48 bits wide, and can be set by
performing two 32-bit writes.
Add support for writing the high 16 bits of the offset register and
update the signature of the WatchdogWriteOffsetRegister function to take
a UINT64 value.
Signed-off-by: Rebecca Cran <rebecca@os.amperecomputing.com>
---
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h | 11 +++++++++-
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 23 +++++++++++++++-----
2 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h
index 9bc3bf47047c..fb117832683f 100644
--- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h
+++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h
@@ -1,9 +1,13 @@
/** @file
*
+* Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR>
* Copyright (c) 2013-2017, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
+* @par Reference(s):
+* - Generic Watchdog specification in Arm Base System Architecture 1.0C:
+* https://developer.arm.com/documentation/den0094/c/
**/
#ifndef GENERIC_WATCHDOG_H_
@@ -14,12 +18,17 @@
// Control Frame:
#define GENERIC_WDOG_CONTROL_STATUS_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x000)
-#define GENERIC_WDOG_OFFSET_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x008)
+#define GENERIC_WDOG_OFFSET_REG_LOW ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x008)
+#define GENERIC_WDOG_OFFSET_REG_HIGH ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x00C)
#define GENERIC_WDOG_COMPARE_VALUE_REG_LOW ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x010)
#define GENERIC_WDOG_COMPARE_VALUE_REG_HIGH ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x014)
+#define GENERIC_WDOG_IID_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0xFCC)
// Values of bit 0 of the Control/Status Register
#define GENERIC_WDOG_ENABLED 1
#define GENERIC_WDOG_DISABLED 0
+#define GENERIC_WDOG_IID_REV_SHIFT 16
+#define GENERIC_WDOG_IID_REV_MASK 0xF
+
#endif // GENERIC_WATCHDOG_H_
diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c
index 66c6c37c08b0..20549aa91d94 100644
--- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c
+++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c
@@ -1,5 +1,6 @@
/** @file
*
+* Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR>
* Copyright (c) 2013-2018, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -35,16 +36,23 @@ STATIC UINTN mTimerFrequencyHz = 0;
It is therefore stored here. 0 means the timer is not running. */
STATIC UINT64 mNumTimerTicks = 0;
+STATIC UINT8 WatchdogRevision;
+
+#define MAX_UINT48 0xFFFFFFFFFFFFULL
+
STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol;
STATIC EFI_WATCHDOG_TIMER_NOTIFY mWatchdogNotify;
STATIC
VOID
WatchdogWriteOffsetRegister (
- UINT32 Value
+ UINT64 Value
)
{
- MmioWrite32 (GENERIC_WDOG_OFFSET_REG, Value);
+ MmioWrite32 (GENERIC_WDOG_OFFSET_REG_LOW, Value & MAX_UINT32);
+ if (WatchdogRevision == 1) {
+ MmioWrite32 (GENERIC_WDOG_OFFSET_REG_HIGH, (Value >> 32) & MAX_UINT16);
+ }
}
STATIC
@@ -211,17 +219,17 @@ WatchdogSetTimerPeriod (
/* If the number of required ticks is greater than the max the watchdog's
offset register (WOR) can hold, we need to manually compute and set
the compare register (WCV) */
- if (mNumTimerTicks > MAX_UINT32) {
+ if (mNumTimerTicks > MAX_UINT48) {
/* We need to enable the watchdog *before* writing to the compare register,
because enabling the watchdog causes an "explicit refresh", which
clobbers the compare register (WCV). In order to make sure this doesn't
trigger an interrupt, set the offset to max. */
- WatchdogWriteOffsetRegister (MAX_UINT32);
+ WatchdogWriteOffsetRegister (MAX_UINT48);
WatchdogEnable ();
SystemCount = ArmGenericTimerGetSystemCount ();
WatchdogWriteCompareRegister (SystemCount + mNumTimerTicks);
} else {
- WatchdogWriteOffsetRegister ((UINT32)mNumTimerTicks);
+ WatchdogWriteOffsetRegister (mNumTimerTicks);
WatchdogEnable ();
}
@@ -310,6 +318,7 @@ GenericWatchdogEntry (
{
EFI_STATUS Status;
EFI_HANDLE Handle;
+ UINT32 WatchdogIId;
Status = gBS->LocateProtocol (
&gHardwareInterrupt2ProtocolGuid,
@@ -367,7 +376,9 @@ GenericWatchdogEntry (
);
ASSERT_EFI_ERROR (Status);
- mNumTimerTicks = 0;
+ mNumTimerTicks = 0;
+ WatchdogIId = MmioRead32 (GENERIC_WDOG_IID_REG);
+ WatchdogRevision = (WatchdogIId >> GENERIC_WDOG_IID_REV_SHIFT) & GENERIC_WDOG_IID_REV_MASK;
WatchdogDisable ();
return EFI_SUCCESS;
--
2.34.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114088): https://edk2.groups.io/g/devel/message/114088
Mute This Topic: https://groups.io/mt/103832319/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Hi Rebecca, Thank you for this patch. Please find my feedback inline marked as [SAMI]. Regards, Sami Mujawar On 19/01/2024, 15:46, "Rebecca Cran" <rebecca@os.amperecomputing.com <mailto:rebecca@os.amperecomputing.com>> wrote: The generic watchdog offset register is 48 bits wide, and can be set by performing two 32-bit writes. Add support for writing the high 16 bits of the offset register and update the signature of the WatchdogWriteOffsetRegister function to take a UINT64 value. Signed-off-by: Rebecca Cran <rebecca@os.amperecomputing.com <mailto:rebecca@os.amperecomputing.com>> --- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h | 11 +++++++++- ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c | 23 +++++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h index 9bc3bf47047c..fb117832683f 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h @@ -1,9 +1,13 @@ /** @file * +* Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> * Copyright (c) 2013-2017, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * +* @par Reference(s): +* - Generic Watchdog specification in Arm Base System Architecture 1.0C: +* https://developer.arm.com/documentation/den0094/c/ <https://developer.arm.com/documentation/den0094/c/> **/ #ifndef GENERIC_WATCHDOG_H_ @@ -14,12 +18,17 @@ // Control Frame: #define GENERIC_WDOG_CONTROL_STATUS_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x000) -#define GENERIC_WDOG_OFFSET_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x008) +#define GENERIC_WDOG_OFFSET_REG_LOW ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x008) +#define GENERIC_WDOG_OFFSET_REG_HIGH ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x00C) #define GENERIC_WDOG_COMPARE_VALUE_REG_LOW ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x010) #define GENERIC_WDOG_COMPARE_VALUE_REG_HIGH ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x014) +#define GENERIC_WDOG_IID_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0xFCC) // Values of bit 0 of the Control/Status Register #define GENERIC_WDOG_ENABLED 1 #define GENERIC_WDOG_DISABLED 0 +#define GENERIC_WDOG_IID_REV_SHIFT 16 +#define GENERIC_WDOG_IID_REV_MASK 0xF [SAMI] I think the above macros should be prefixed as GENERIC_WDOG_IID_ARCH_REV_ as this is the Generic Watchdog architecture revision and not the Component revision. + #endif // GENERIC_WATCHDOG_H_ diff --git a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c index 66c6c37c08b0..20549aa91d94 100644 --- a/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c +++ b/ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c @@ -1,5 +1,6 @@ /** @file * +* Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> * Copyright (c) 2013-2018, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent @@ -35,16 +36,23 @@ STATIC UINTN mTimerFrequencyHz = 0; It is therefore stored here. 0 means the timer is not running. */ STATIC UINT64 mNumTimerTicks = 0; +STATIC UINT8 WatchdogRevision; [SAMI] Similarly this should be changed to WatchdogArchRevision. + +#define MAX_UINT48 0xFFFFFFFFFFFFULL + STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol; STATIC EFI_WATCHDOG_TIMER_NOTIFY mWatchdogNotify; STATIC VOID WatchdogWriteOffsetRegister ( - UINT32 Value + UINT64 Value ) { - MmioWrite32 (GENERIC_WDOG_OFFSET_REG, Value); + MmioWrite32 (GENERIC_WDOG_OFFSET_REG_LOW, Value & MAX_UINT32); + if (WatchdogRevision == 1) { + MmioWrite32 (GENERIC_WDOG_OFFSET_REG_HIGH, (Value >> 32) & MAX_UINT16); + } } STATIC @@ -211,17 +219,17 @@ WatchdogSetTimerPeriod ( /* If the number of required ticks is greater than the max the watchdog's offset register (WOR) can hold, we need to manually compute and set the compare register (WCV) */ - if (mNumTimerTicks > MAX_UINT32) { + if (mNumTimerTicks > MAX_UINT48) { [SAMI] The SBSA 3.1 spec https://developer.arm.com/documentation/den0029/a/?lang=en, Revision 3.1A, section 5.2, states 'The watchdog offset register is 32 bits wide.' Considering that, I think the above check should be MAX_UINT32 for WatchdogArchRevision == 0. I think it may be good to define a static function GetMaxWatchdogOffsetRegisterValue() that does the arch revision check and returns either MAX_UINT32 or MAX_UINT48. [/SAMI] /* We need to enable the watchdog *before* writing to the compare register, because enabling the watchdog causes an "explicit refresh", which clobbers the compare register (WCV). In order to make sure this doesn't trigger an interrupt, set the offset to max. */ - WatchdogWriteOffsetRegister (MAX_UINT32); + WatchdogWriteOffsetRegister (MAX_UINT48); WatchdogEnable (); SystemCount = ArmGenericTimerGetSystemCount (); WatchdogWriteCompareRegister (SystemCount + mNumTimerTicks); } else { - WatchdogWriteOffsetRegister ((UINT32)mNumTimerTicks); + WatchdogWriteOffsetRegister (mNumTimerTicks); WatchdogEnable (); } @@ -310,6 +318,7 @@ GenericWatchdogEntry ( { EFI_STATUS Status; EFI_HANDLE Handle; + UINT32 WatchdogIId; [SAMI] Minor, the above variable name should be WatchdogIid to comply with the coding standard. Status = gBS->LocateProtocol ( &gHardwareInterrupt2ProtocolGuid, @@ -367,7 +376,9 @@ GenericWatchdogEntry ( ); ASSERT_EFI_ERROR (Status); - mNumTimerTicks = 0; + mNumTimerTicks = 0; + WatchdogIId = MmioRead32 (GENERIC_WDOG_IID_REG); + WatchdogRevision = (WatchdogIId >> GENERIC_WDOG_IID_REV_SHIFT) & GENERIC_WDOG_IID_REV_MASK; WatchdogDisable (); return EFI_SUCCESS; -- 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114200): https://edk2.groups.io/g/devel/message/114200 Mute This Topic: https://groups.io/mt/103832319/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
On 1/23/2024 7:10 AM, Sami Mujawar wrote: > @@ -310,6 +318,7 @@ GenericWatchdogEntry ( > { > EFI_STATUS Status; > EFI_HANDLE Handle; > + UINT32 WatchdogIId; > [SAMI] Minor, the above variable name should be WatchdogIid to comply with the coding standard. I was wondering about the naming, since it's the "Watchdog Interface ID". Since the second "I" is for another word, should it still be lower-case? -- Rebecca Cran -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114351): https://edk2.groups.io/g/devel/message/114351 Mute This Topic: https://groups.io/mt/103832319/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
Hi Rebecca, On 24/01/2024, 19:36, "Rebecca Cran" <rebecca@os.amperecomputing.com <mailto:rebecca@os.amperecomputing.com>> wrote: On 1/23/2024 7:10 AM, Sami Mujawar wrote: > @@ -310,6 +318,7 @@ GenericWatchdogEntry ( > { > EFI_STATUS Status; > EFI_HANDLE Handle; > + UINT32 WatchdogIId; > [SAMI] Minor, the above variable name should be WatchdogIid to comply with the coding standard. I was wondering about the naming, since it's the "Watchdog Interface ID". Since the second "I" is for another word, should it still be lower-case? [SAMI] I agree. If it passes the CI checks (uncrustify/ecc), I think it should be ok. Regards, Sami Mujawar -- Rebecca Cran -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114381): https://edk2.groups.io/g/devel/message/114381 Mute This Topic: https://groups.io/mt/103832319/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.