rust/bindings/bindings_helper.h | 1 + rust/helpers/helpers.c | 1 + rust/helpers/irq.c | 9 + rust/helpers/pci.c | 8 + rust/kernel/irq.rs | 22 ++ rust/kernel/irq/flags.rs | 124 ++++++++++ rust/kernel/irq/request.rs | 490 ++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + rust/kernel/pci.rs | 45 +++- rust/kernel/platform.rs | 146 +++++++++++- 10 files changed, 844 insertions(+), 3 deletions(-)
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/ Changes in v6: - Fixed some typos in the docs (thanks, Dirk!) - Reordered the arguments for the accessors in platform.rs (Danilo) - Renamed handle_on_thread() to handle_threaded() (Danilo) - Changed the documentation for Handler and ThreadedHandler to what Danilo suggested - Link to v5: https://lore.kernel.org/r/20250627-topics-tyr-request_irq-v5-0-0545ee4dadf6@collabora.com Changes in v5: Thanks, Danilo { - Removed extra scope in the examples. - Renamed Registration::register() to Registration::new(), - Switched to try_pin_init! in Registration::new() (thanks for the code and the help, Boqun and Benno) - Renamed the trait functions to handle() and handle_on_thread(). - Introduced IrqRequest with an unsafe pub(crate) constructor - Made both register() and the accessors that return IrqRequest public the idea is to allow both of these to work: // `irq` is an `irq::Registration` let irq = pdev.threaded_irq_by_name()? and // `req` is an `IrqRequest`. let req = pdev.irq_by_name()?; // `irq` is an `irq::Registration` let irq = irq::ThreadedRegistration::new(req)?; - Added another name in the byname variants. There's now one for the request part and the other one to register() - Reworked the examples in request.rs - Implemented the irq accessors in place for pci.rs - Split the platform accessor macros into two } - Added a rust helper for pci_irq_vectors if !CONFIG_PCI_MSI (thanks, Intel 0day bot) - Link to v4: https://lore.kernel.org/r/20250608-topics-tyr-request_irq-v4-0-81cb81fb8073@collabora.com Changes in v4: Thanks, Benno { - Split series into more patches (see patches 1-4) - Use cast() where possible - Merge pub use statements. - Add {Threaded}IrqReturn::into_inner() instead of #[repr(u32)] - Used AtomicU32 instead of SpinLock to add interior mutability to the handler's data. SpinLockIrq did not land yet. - Mention that `&self` is !Unpin and was initialized using pin_init in drop() - Fix the docs slightly } - Add {try_}synchronize_irq(). - Use Devres for the irq registration (see RegistrationInner). This idea was suggested by Danilo and Alice. - Added PCI accessors (as asked by Joel Fernandez) - Fix a major oversight: we were passing in a pointer to Registration in register_{threaded}_irq() but casting it to Handler/ThreadedHandler in the callbacks. - Make register() pub(crate) so drivers can only retrieve registrations through device-specific accessors. This forbids drivers from trying to register an invalid irq. - I think this will still go through a few rounds, so I'll defer the patch to update MAINTAINERS for now. - Link to v3: https://lore.kernel.org/r/20250514-topics-tyr-request_irq-v3-0-d6fcc2591a88@collabora.com Changes in v3: - Rebased on driver-core-next - Added patch to get the irq numbers from a platform device (thanks, Christian!) - Split flags into its own file. - Change iff to "if and only if" - Implement PartialEq and Eq for Flags - Fix some broken docs/markdown - Reexport most things so users can elide ::request from the path - Add a blanket implementation of ThreadedHandler and Handler for Arc/Box<T: Handler> that just forwards the call to the T. This lets us have Arc<Foo> and Box<Foo> as handlers if Foo: Handler. - Rework the examples a bit. - Remove "as _" casts in favor of "as u64" for flags. This is needed to cast the individual flags into u64. - Use #[repr(u32)] for ThreadedIrqReturn and IrqReturn. - Wrapped commit messages to < 75 characters - Link to v2: https://lore.kernel.org/r/20250122163932.46697-1-daniel.almeida@collabora.com Changes in v2: - Added Co-developed-by tag to account for the work that Alice did in order to figure out how to do this without Opaque<T> (Thanks!) - Removed Opaque<T> in favor of plain T - Fixed the examples - Made sure that the invariants sections are the last entry in the docs - Switched to slot.cast() where applicable, - Mentioned in the safety comments that we require that T: Sync, - Removed ThreadedFnReturn in favor of IrqReturn, - Improved the commit message Link to v1: https://lore.kernel.org/rust-for-linux/20241024-topic-panthor-rs-request_irq-v1-1-7cbc51c182ca@collabora.com/ --- Daniel Almeida (6): rust: irq: add irq module rust: irq: add flags module rust: irq: add support for non-threaded IRQs and handlers rust: irq: add support for threaded IRQs and handlers rust: platform: add irq accessors rust: pci: add irq accessors rust/bindings/bindings_helper.h | 1 + rust/helpers/helpers.c | 1 + rust/helpers/irq.c | 9 + rust/helpers/pci.c | 8 + rust/kernel/irq.rs | 22 ++ rust/kernel/irq/flags.rs | 124 ++++++++++ rust/kernel/irq/request.rs | 490 ++++++++++++++++++++++++++++++++++++++++ rust/kernel/lib.rs | 1 + rust/kernel/pci.rs | 45 +++- rust/kernel/platform.rs | 146 +++++++++++- 10 files changed, 844 insertions(+), 3 deletions(-) --- base-commit: 3964d07dd821efe9680e90c51c86661a98e60a0f change-id: 20250712-topics-tyr-request_irq2-ae7ee9b85854 Best regards, -- Daniel Almeida <daniel.almeida@collabora.com>
On Tue, Jul 15, 2025 at 12:16:37PM -0300, Daniel Almeida wrote: > Changes in v7: Hello, Daniel, I tested this series on an Nvidia 3090 GPU running the Nova project and I am able to register and receive interrupts (there are several WIP patches for Nova that are needed but your series is a dependency). We are looking forward to having these patches upstream, please feel free to add my tag to the patches: Tested-by: Joel Fernandes <joelagnelf@nvidia.com> thanks, - Joel > - 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/ > > Changes in v6: > - Fixed some typos in the docs (thanks, Dirk!) > - Reordered the arguments for the accessors in platform.rs (Danilo) > - Renamed handle_on_thread() to handle_threaded() (Danilo) > - Changed the documentation for Handler and ThreadedHandler to what > Danilo suggested > - Link to v5: https://lore.kernel.org/r/20250627-topics-tyr-request_irq-v5-0-0545ee4dadf6@collabora.com > > Changes in v5: > > Thanks, Danilo { > - Removed extra scope in the examples. > - Renamed Registration::register() to Registration::new(), > - Switched to try_pin_init! in Registration::new() (thanks for the > code and the help, Boqun and Benno) > - Renamed the trait functions to handle() and handle_on_thread(). > - Introduced IrqRequest with an unsafe pub(crate) constructor > - Made both register() and the accessors that return IrqRequest public > the idea is to allow both of these to work: > // `irq` is an `irq::Registration` > let irq = pdev.threaded_irq_by_name()? > and > // `req` is an `IrqRequest`. > let req = pdev.irq_by_name()?; > // `irq` is an `irq::Registration` > let irq = irq::ThreadedRegistration::new(req)?; > > - Added another name in the byname variants. There's now one for the > request part and the other one to register() > - Reworked the examples in request.rs > - Implemented the irq accessors in place for pci.rs > - Split the platform accessor macros into two > } > > - Added a rust helper for pci_irq_vectors if !CONFIG_PCI_MSI (thanks, > Intel 0day bot) > - Link to v4: https://lore.kernel.org/r/20250608-topics-tyr-request_irq-v4-0-81cb81fb8073@collabora.com > > Changes in v4: > > Thanks, Benno { > - Split series into more patches (see patches 1-4) > - Use cast() where possible > - Merge pub use statements. > - Add {Threaded}IrqReturn::into_inner() instead of #[repr(u32)] > - Used AtomicU32 instead of SpinLock to add interior mutability to the > handler's data. SpinLockIrq did not land yet. > - Mention that `&self` is !Unpin and was initialized using pin_init in > drop() > - Fix the docs slightly > } > > - Add {try_}synchronize_irq(). > - Use Devres for the irq registration (see RegistrationInner). This idea > was suggested by Danilo and Alice. > - Added PCI accessors (as asked by Joel Fernandez) > - Fix a major oversight: we were passing in a pointer to Registration > in register_{threaded}_irq() but casting it to Handler/ThreadedHandler in > the callbacks. > - Make register() pub(crate) so drivers can only retrieve registrations > through device-specific accessors. This forbids drivers from trying to > register an invalid irq. > - I think this will still go through a few rounds, so I'll defer the > patch to update MAINTAINERS for now. > > - Link to v3: https://lore.kernel.org/r/20250514-topics-tyr-request_irq-v3-0-d6fcc2591a88@collabora.com > > Changes in v3: > - Rebased on driver-core-next > - Added patch to get the irq numbers from a platform device (thanks, > Christian!) > - Split flags into its own file. > - Change iff to "if and only if" > - Implement PartialEq and Eq for Flags > - Fix some broken docs/markdown > - Reexport most things so users can elide ::request from the path > - Add a blanket implementation of ThreadedHandler and Handler for > Arc/Box<T: Handler> that just forwards the call to the T. This lets us > have Arc<Foo> and Box<Foo> as handlers if Foo: Handler. > - Rework the examples a bit. > - Remove "as _" casts in favor of "as u64" for flags. This is needed to > cast the individual flags into u64. > - Use #[repr(u32)] for ThreadedIrqReturn and IrqReturn. > - Wrapped commit messages to < 75 characters > > - Link to v2: https://lore.kernel.org/r/20250122163932.46697-1-daniel.almeida@collabora.com > > Changes in v2: > - Added Co-developed-by tag to account for the work that Alice did in order to > figure out how to do this without Opaque<T> (Thanks!) > - Removed Opaque<T> in favor of plain T > - Fixed the examples > - Made sure that the invariants sections are the last entry in the docs > - Switched to slot.cast() where applicable, > - Mentioned in the safety comments that we require that T: Sync, > - Removed ThreadedFnReturn in favor of IrqReturn, > - Improved the commit message > > Link to v1: https://lore.kernel.org/rust-for-linux/20241024-topic-panthor-rs-request_irq-v1-1-7cbc51c182ca@collabora.com/ > > --- > Daniel Almeida (6): > rust: irq: add irq module > rust: irq: add flags module > rust: irq: add support for non-threaded IRQs and handlers > rust: irq: add support for threaded IRQs and handlers > rust: platform: add irq accessors > rust: pci: add irq accessors > > rust/bindings/bindings_helper.h | 1 + > rust/helpers/helpers.c | 1 + > rust/helpers/irq.c | 9 + > rust/helpers/pci.c | 8 + > rust/kernel/irq.rs | 22 ++ > rust/kernel/irq/flags.rs | 124 ++++++++++ > rust/kernel/irq/request.rs | 490 ++++++++++++++++++++++++++++++++++++++++ > rust/kernel/lib.rs | 1 + > rust/kernel/pci.rs | 45 +++- > rust/kernel/platform.rs | 146 +++++++++++- > 10 files changed, 844 insertions(+), 3 deletions(-) > --- > base-commit: 3964d07dd821efe9680e90c51c86661a98e60a0f > change-id: 20250712-topics-tyr-request_irq2-ae7ee9b85854 > > Best regards, > -- > Daniel Almeida <daniel.almeida@collabora.com> >
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@de.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. ...
On Tue Jul 15, 2025 at 5:16 PM CEST, Daniel Almeida wrote: > Daniel Almeida (6): > rust: irq: add irq module > rust: irq: add flags module > rust: irq: add support for non-threaded IRQs and handlers > rust: irq: add support for threaded IRQs and handlers > rust: platform: add irq accessors > rust: pci: add irq accessors (Mostly copy-paste from v6 [1].) What's the intended merge path for this series? Should I take it through driver-core, in case we make it for the upcoming merge window? I'd assume so, given that, besides the series also containing platform and PCI patches, it depends on patches that are in driver-core-next. @Thomas: Is there any agreement on how the IRQ Rust code should be maintained? What's your preference? - Danilo [1] https://lore.kernel.org/lkml/aGbkfa57bDa1mzI7@pollux/
© 2016 - 2025 Red Hat, Inc.