lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <dd34e5f4-5027-4096-9f32-129c8a067d0a@de.bosch.com>
Date: Tue, 22 Jul 2025 13:41:46 +0200
From: Dirk Behme <dirk.behme@...bosch.com>
To: Daniel Almeida <daniel.almeida@...labora.com>, Miguel Ojeda
	<ojeda@...nel.org>, Alex Gaynor <alex.gaynor@...il.com>, Boqun Feng
	<boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>,
	Björn Roy Baron <bjorn3_gh@...tonmail.com>, Andreas Hindborg
	<a.hindborg@...nel.org>, Alice Ryhl <aliceryhl@...gle.com>, Trevor Gross
	<tmgross@...ch.edu>, Danilo Krummrich <dakr@...nel.org>, Greg Kroah-Hartman
	<gregkh@...uxfoundation.org>, "Rafael J. Wysocki" <rafael@...nel.org>, Thomas
 Gleixner <tglx@...utronix.de>, Bjorn Helgaas <bhelgaas@...gle.com>,
	Krzysztof Wilczyński <kwilczynski@...nel.org>, Benno Lossin
	<lossin@...nel.org>
CC: <linux-kernel@...r.kernel.org>, <rust-for-linux@...r.kernel.org>,
	<linux-pci@...r.kernel.org>, Geert Uytterhoeven <geert+renesas@...der.be>,
	Wolfram Sang <wsa+renesas@...g-engineering.com>
Subject: Re: [PATCH v7 0/6] rust: add support for request_irq

On 15/07/2025 17:16, Daniel Almeida wrote:
> Changes in v7:
> - Rebased on top of driver-core-next
> - Added Flags::new(), which is a const fn. This lets us use build_assert!()
>   to verify the casts (hopefully this is what you meant, Alice?)
> - Changed the Flags inner type to take c_ulong directly, to minimize casts
>   (Thanks, Alice)
> - Moved the flag constants into Impl Flags, instead of using a separate
>   module (Alice)
> - Reverted to using #[repr(u32)] in Threaded/IrqReturn (Thanks Alice,
>   Benno)
> - Fixed all instances where the full path was specified for types in the
>   prelude (Alice)
> - Removed 'static from the CStr used to perform the lookup in the platform
>   accessor (Alice)
> - Renamed the PCI accessors, as asked by Danilo
> - Added more docs to Flags, going into more detail on what they do and how
>   to use them (Miguel)
> - Fixed the indentation in some of the docs (Alice)
> - Added Alice's r-b as appropriate
> - Link to v6: https://lore.kernel.org/rust-for-linux/20250703-topics-tyr-request_irq-v6-0-74103bdc7c52@collabora.com/


Looking for an easy way to test interrupts on an ARM64 Renesas RCar3 SoC
I found a quite simple timer unit (TMU) which has a configurable (start
value & frequency) count down. An interrupt is generated when the
counter reaches 0. And the counter restarts then. There is a C driver
for this already [1].

Using this patch series together with Alice's [2] I got a quite simple
periodic 1 min interrupt handling to run (just for testing, of course
not a full driver): [3] (output [4]).

With that:

Tested-by: Dirk Behme <dirk.behme@...bosch.com>

Thanks to Daniel for the support!

Dirk

[1]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/sh_tmu.c

[2]
https://lore.kernel.org/rust-for-linux/20250721-irq-bound-device-v1-1-4fb2af418a63@google.com/

[3]

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 645f517a1ac2..d009a0e3508c 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -554,7 +554,16 @@ config RENESAS_OSTM
 	  Enables the support for the Renesas OSTM.

 config SH_TIMER_TMU
-	bool "Renesas TMU timer driver" if COMPILE_TEST
+	bool "Renesas TMU timer driver"
+	depends on HAS_IOMEM
+	default SYS_SUPPORTS_SH_TMU
+	help
+	  This enables build of a clocksource and clockevent driver for
+	  the 32-bit Timer Unit (TMU) hardware available on a wide range
+	  SoCs from Renesas.
+
+config SH_TIMER_TMU_RUST
+	bool "Renesas TMU Rust timer driver"
 	depends on HAS_IOMEM
 	default SYS_SUPPORTS_SH_TMU
 	help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 205bf3b0a8f3..66567f871502 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_SH_TIMER_CMT)	+= sh_cmt.o
 obj-$(CONFIG_SH_TIMER_MTU2)	+= sh_mtu2.o
 obj-$(CONFIG_RENESAS_OSTM)	+= renesas-ostm.o
 obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
+obj-$(CONFIG_SH_TIMER_TMU_RUST)	+= sh_tmu_rust.o
 obj-$(CONFIG_EM_TIMER_STI)	+= em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)	+= i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
diff --git a/drivers/clocksource/sh_tmu_rust.rs
b/drivers/clocksource/sh_tmu_rust.rs
new file mode 100644
index 000000000000..328f9541d1bb
--- /dev/null
+++ b/drivers/clocksource/sh_tmu_rust.rs
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust Renesas TMU driver.
+
+use kernel::{
+    c_str,
+    device::{Core, Device, Bound},
+    devres::Devres,
+    io::mem::IoMem,
+    irq::{flags::Flags, IrqReturn, Registration},
+    of, platform,
+    prelude::*,
+    sync::Arc,
+    types::ARef,
+};
+
+struct RenesasTMUDriver {
+    pdev: ARef<platform::Device>,
+    _registration: Arc<Registration<Handler>>,
+    _iomem: Arc<Devres<IoMem>>,
+}
+
+struct Info;
+
+kernel::of_device_table!(
+    OF_TABLE,
+    MODULE_OF_TABLE,
+    <RenesasTMUDriver as platform::Driver>::IdInfo,
+    [(of::DeviceId::new(c_str!("renesas,tmu")), Info)]
+);
+
+const TSTR: usize =  0x4; //  8 Bit register
+const TCOR: usize =  0x8; // 32 Bit register
+const TCNT: usize =  0xC; // 32 Bit register
+const TCR:  usize = 0x10; // 16 Bit register
+
+struct Handler {
+    iomem: Arc<Devres<IoMem>>,
+}
+
+impl kernel::irq::request::Handler for Handler {
+    fn handle(&self, dev: &Device<Bound>) -> IrqReturn {
+        pr_info!("Renesas TMU IRQ handler called.\n");
+
+        // Reset the underflow flag
+        let io = self.iomem.access(dev).unwrap();
+        let tcr = io.try_read16_relaxed(TCR).unwrap_or(0);
+        if tcr & (0x1 << 8) != 0 {
+            io.try_write16_relaxed(tcr & !(0x1 << 8), TCR).unwrap_or(());
+        }
+
+        IrqReturn::Handled
+    }
+}
+
+impl platform::Driver for RenesasTMUDriver {
+    type IdInfo = Info;
+    const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+
+    fn probe(
+        pdev: &platform::Device<Core>,
+        _info: Option<&Self::IdInfo>,
+    ) -> Result<Pin<KBox<Self>>> {
+        let dev = pdev.as_ref();
+
+        dev_dbg!(dev, "Probe Rust Renesas TMU driver.\n");
+
+        let request = pdev.request_io_by_index(0).ok_or(EINVAL)?;
+        let iomem = Arc::pin_init(request.iomap()?, GFP_KERNEL)?;
+        let io = Arc::pin_init(iomem.access(dev)?, GFP_KERNEL)?;
+
+        // Set count to 1 minute. Clock is 16.66MHz / 4 = 4.165MHz
+        let timeout = 4165000 * 60; // 1 minute in clock ticks
+        io.try_write32_relaxed(timeout, TCOR)?;
+        io.try_write32_relaxed(timeout, TCNT)?;
+        // Enable underflow interrupt (UNIE, Underflow Interrupt Control)
+        let tcr = io.try_read16_relaxed(TCR)?;
+        io.try_write16_relaxed(tcr | 0x1 << 5, TCR)?;
+
+        let request = pdev.irq_by_index(0)?;
+        dev_info!(dev, "IRQ:  {}\n", request.irq());
+        let registration = Registration::new(request, Flags::SHARED,
c_str!("tmu"), Handler{iomem: iomem.clone()});
+        let registration = Arc::pin_init(registration, GFP_KERNEL)?;
+
+        // Enable TMU
+        io.try_write8_relaxed(0x1, TSTR)?;
+        // Read back registers to verify
+        dev_info!(dev, "TSTR: 0x{:x}\n", io.try_read8_relaxed(TSTR)?);
+        dev_info!(dev, "TCOR: 0x{:x}\n", io.try_read32_relaxed(TCOR)?);
+        dev_info!(dev, "TCNT: 0x{:x}\n", io.try_read32_relaxed(TCNT)?);
+        dev_info!(dev, "TCR:  0x{:x}\n", io.try_read16_relaxed(TCR)?);
+
+        let drvdata = KBox::pin_init(Self { pdev: pdev.into(),
_registration: registration, _iomem: iomem.clone()}, GFP_KERNEL)?;
+
+        dev_info!(dev, "probe done\n");
+
+        Ok(drvdata)
+    }
+}
+
+impl Drop for RenesasTMUDriver {
+    fn drop(&mut self) {
+        dev_dbg!(self.pdev.as_ref(), "Remove Rust Renesas TMU driver.\n");
+    }
+}
+
+kernel::module_platform_driver! {
+    type: RenesasTMUDriver,
+    name: "rust_tmu",
+    authors: ["Dirk Behme"],
+    description: "Rust Renesas TMU driver",
+    license: "GPL v2",
+}

[4] Interrupt each 60s:

...
[  430.655055] rust_tmu: Renesas TMU IRQ handler called.
[  490.637054] rust_tmu: Renesas TMU IRQ handler called.
[  550.619052] rust_tmu: Renesas TMU IRQ handler called.
[  610.601050] rust_tmu: Renesas TMU IRQ handler called.
[  670.583049] rust_tmu: Renesas TMU IRQ handler called.
[  730.565047] rust_tmu: Renesas TMU IRQ handler called.
...




Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ