rust/hw/meson.build | 1 + .../watchdog/cmsdk_apb_watchdog/meson.build | 19 +++ .../watchdog/cmsdk_apb_watchdog/src/device.rs | 110 ++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 rust/hw/watchdog/cmsdk_apb_watchdog/meson.build create mode 100644 rust/hw/watchdog/cmsdk_apb_watchdog/src/device.rs
Hello,
This patch introduces a Rust implementation of the CMSDK APB Watchdog
(originally hw/watchdog/cmsdk-apb-watchdog.c).
The implementation functions as a drop-in replacement that:
1. Implements the ResettablePhasesImpl trait for hardware resets.
2. Uses BqlCell for thread-safe register access.
3. Maps the MMIO read/write logic to the Rust MemoryRegionOpsBuilder.
I welcome any feedback on the implementation or the usage of the safe
bindings.
Signed-off-by: Mohd Kashif Khan <kashif04x@gmail.com>
From adedbb3b88c6cc06c9fa15c6ae7df6e6130bcd81 Mon Sep 17 00:00:00 2001
From: Mohd Kashif Khan <kashif04x@gmail.com>
Date: Tue, 27 Jan 2026 20:57:44 +0530
Subject: [RFC PATCH] rust: add CMSDK APB Watchdog device
This patch introduces a Rust implementation of the CMSDK APB Watchdog
(originally hw/watchdog/cmsdk-apb-watchdog.c).
The implementation functions as a drop-in replacement that:
1. Implements the ResettablePhasesImpl trait for hardware resets.
2. Uses BqlCell for thread-safe register access.
3. Maps the MMIO read/write logic to the Rust MemoryRegionOpsBuilder.
Signed-off-by: Mohd Kashif Khan <kashif04x@gmail.com>
---
rust/hw/meson.build | 1 +
.../watchdog/cmsdk_apb_watchdog/meson.build | 19 +++
.../watchdog/cmsdk_apb_watchdog/src/device.rs | 110 ++++++++++++++++++
3 files changed, 130 insertions(+)
create mode 100644 rust/hw/watchdog/cmsdk_apb_watchdog/meson.build
create mode 100644 rust/hw/watchdog/cmsdk_apb_watchdog/src/device.rs
diff --git a/rust/hw/meson.build b/rust/hw/meson.build
index 9749d4adfc..b7c912d5c9 100644
--- a/rust/hw/meson.build
+++ b/rust/hw/meson.build
@@ -1,2 +1,3 @@
subdir('char')
subdir('timer')
+subdir('watchdog/cmsdk_apb_watchdog')
\ No newline at end of file
diff --git a/rust/hw/watchdog/cmsdk_apb_watchdog/meson.build b/rust/hw/watchdog/cmsdk_apb_watchdog/meson.build
new file mode 100644
index 0000000000..7a86a5360a
--- /dev/null
+++ b/rust/hw/watchdog/cmsdk_apb_watchdog/meson.build
@@ -0,0 +1,19 @@
+_lib_cmsdk_apb_watchdog = static_library(
+ 'cmsdk_apb_watchdog',
+ files('src/device.rs'),
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ link_with: [
+ _util_rs,
+ _bql_rs,
+ _qom_rs,
+ _system_rs,
+ _hwcore_rs,
+ ],
+ dependencies: [common_rs],
+)
+
+rust_devices_ss.add(declare_dependency(
+ link_whole: [_lib_cmsdk_apb_watchdog],
+ variables: {'crate': 'cmsdk_apb_watchdog'},
+))
\ No newline at end of file
diff --git a/rust/hw/watchdog/cmsdk_apb_watchdog/src/device.rs b/rust/hw/watchdog/cmsdk_apb_watchdog/src/device.rs
new file mode 100644
index 0000000000..cd4dfce36d
--- /dev/null
+++ b/rust/hw/watchdog/cmsdk_apb_watchdog/src/device.rs
@@ -0,0 +1,110 @@
+use std::ffi::CStr;
+
+use bql::prelude::*;
+use common::prelude::*;
+use hwcore::prelude::*;
+use qom::prelude::*;
+use system::prelude::*;
+
+// 1. Type Name
+pub const TYPE_CMSDK_APB_WATCHDOG: &CStr = c"cmsdk-apb-watchdog";
+
+// 2. The Struct
+#[repr(C)]
+#[derive(qom::Object, hwcore::Device)]
+pub struct CmsdkApbWatchdog {
+ parent_obj: ParentField<SysBusDevice>,
+ iomem: MemoryRegion,
+ control: BqlCell<u32>,
+ load: BqlCell<u32>,
+ value: BqlCell<u32>,
+ lock: BqlCell<u32>,
+}
+
+// 3. Logic Implementation
+impl CmsdkApbWatchdog {
+ fn read(&self, offset: u64, _size: u32) -> u64 {
+ match offset {
+ 0x0 => self.load.get() as u64,
+ 0x4 => self.value.get() as u64,
+ 0x8 => self.control.get() as u64,
+ 0xC00 => self.lock.get() as u64,
+ _ => 0,
+ }
+ }
+
+ fn write(&self, offset: u64, value: u64, _size: u32) {
+ if self.lock.get() == 1 && offset != 0xC00 {
+ return;
+ }
+
+ match offset {
+ 0x0 => self.load.set(value as u32),
+ 0x4 => {},
+ 0x8 => self.control.set(value as u32),
+ 0xC00 => {
+ if value == 0x1ACCE551 {
+ self.lock.set(0);
+ } else {
+ self.lock.set(1);
+ }
+ },
+ _ => {},
+ }
+ }
+
+ fn reset(&self, _type: ResetType) {
+ self.control.set(0);
+ self.load.set(0);
+ self.value.set(0);
+ self.lock.set(0);
+ }
+
+ unsafe fn init(mut this: ParentInit<Self>) {
+ static OPS: MemoryRegionOps<CmsdkApbWatchdog> =
+ MemoryRegionOpsBuilder::<CmsdkApbWatchdog>::new()
+ .read(&CmsdkApbWatchdog::read)
+ .write(&CmsdkApbWatchdog::write)
+ .little_endian()
+ .impl_sizes(4, 4)
+ .build();
+
+ MemoryRegion::init_io(
+ &mut uninit_field_mut!(*this, iomem),
+ &OPS,
+ "cmsdk-apb-watchdog",
+ 0x1000,
+ );
+
+ uninit_field_mut!(*this, control).write(BqlCell::new(0));
+ uninit_field_mut!(*this, load).write(BqlCell::new(0));
+ uninit_field_mut!(*this, value).write(BqlCell::new(0));
+ uninit_field_mut!(*this, lock).write(BqlCell::new(0));
+ }
+
+ fn post_init(&self) {
+ self.init_mmio(&self.iomem);
+ }
+}
+
+// 4. Registration Glue
+qom_isa!(CmsdkApbWatchdog: SysBusDevice, DeviceState, Object);
+
+unsafe impl ObjectType for CmsdkApbWatchdog {
+ type Class = <SysBusDevice as ObjectType>::Class;
+ const TYPE_NAME: &'static CStr = TYPE_CMSDK_APB_WATCHDOG;
+}
+
+impl ObjectImpl for CmsdkApbWatchdog {
+ type ParentType = SysBusDevice;
+ const INSTANCE_INIT: Option<unsafe fn(ParentInit<Self>)> = Some(Self::init);
+ const INSTANCE_POST_INIT: Option<fn(&Self)> = Some(Self::post_init);
+ const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>;
+}
+
+impl ResettablePhasesImpl for CmsdkApbWatchdog {
+ const HOLD: Option<fn(&Self, ResetType)> = Some(Self::reset);
+}
+
+impl DeviceImpl for CmsdkApbWatchdog {}
+impl SysBusDeviceImpl for CmsdkApbWatchdog {}
\ No newline at end of file
--
2.43.0
On 1/27/26 16:51, Mohd Kashif Khan wrote: > Hello, > > This patch introduces a Rust implementation of the CMSDK APB Watchdog > (originally hw/watchdog/cmsdk-apb-watchdog.c). > > The implementation functions as a drop-in replacement that: > 1. Implements the ResettablePhasesImpl trait for hardware resets. > 2. Uses BqlCell for thread-safe register access. > 3. Maps the MMIO read/write logic to the Rust MemoryRegionOpsBuilder. > > I welcome any feedback on the implementation or the usage of the safe > bindings. > > Signed-off-by: Mohd Kashif Khan <kashif04x@gmail.com > <mailto:kashif04x@gmail.com>> Hi, would you please change it to use BqlRefCell instead? Also, right now the device is added always to the build. You need to add alternative configuration symbols similar to how pl011 has both PL011_C and X_PL011_RUST. Thanks, Paolo
© 2016 - 2026 Red Hat, Inc.