Rust for Linux List
 help / color / mirror / Atom feed
From: Beata Michalska <beata.michalska@arm.com>
To: ojeda@kernel.org, dakr@kernel.org, gregkh@linuxfoundation.org,
	rafael@kernel.org
Cc: boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com,
	lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com,
	tmgross@umich.edu, daniel.almeida@collabora.com,
	boris.brezillon@collabora.com, work@onurozkan.dev,
	samitolvanen@google.com, rust-for-linux@vger.kernel.org,
	driver-core@lists.linux.dev, linux-kernel@vger.kernel.org,
	linux-pm@vger.kernel.org
Subject: [PATCH v2 3/3] drm/tyr: enable runtime PM
Date: Tue, 21 Jul 2026 17:34:04 +0200	[thread overview]
Message-ID: <20260721153617.869933-4-beata.michalska@arm.com> (raw)
In-Reply-To: <20260721153617.869933-1-beata.michalska@arm.com>

Add runtime PM support to the Tyr platform driver. Move the clocks and
regulators used by runtime suspend and resume into the PM payload, register the
PM callbacks, configure autosuspend, and let DRM paths take a PM usage
reference while querying device state.

Signed-off-by: Beata Michalska <beata.michalska@arm.com>
---
 drivers/gpu/drm/tyr/driver.rs | 112 ++++++++++++++++++++++++++++------
 drivers/gpu/drm/tyr/file.rs   |   7 ++-
 2 files changed, 98 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index 8348c6cd3929..89fe216be0de 100644
--- a/drivers/gpu/drm/tyr/driver.rs
+++ b/drivers/gpu/drm/tyr/driver.rs
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 or MIT
 
 use kernel::{
+    bindings,
     clk::{
         Clk,
         OptionalClk, //
@@ -20,16 +21,16 @@
         poll,
         Io, //
     },
-    new_mutex,
     of,
     platform,
+    pm,
+    pm::*,
     prelude::*,
     regulator,
     regulator::Regulator,
     sizes::SZ_2M,
     sync::{
         aref::ARef,
-        Mutex, //
     },
     time, //
 };
@@ -55,18 +56,21 @@
 pub(crate) struct TyrPlatformDriverData<'bound> {
     _device: ARef<TyrDrmDevice>,
     _reg: drm::Registration<'bound, TyrDrmDriver>,
+    // This needs to be dropped after drm::Registration as this one borrows
+    // borrows PMContext.
+    pub(crate) pm: pm::Registration<'bound, TyrPlatformDriver>,
+
+}
+
+#[pin_data]
+pub(crate) struct TyrRuntimePM<'bound> {
+    pub(crate) pm: PMContext<'bound, TyrPlatformDriver>,
 }
 
 #[pin_data]
 pub(crate) struct TyrDrmDeviceData {
     pub(crate) pdev: ARef<platform::Device>,
 
-    #[pin]
-    clks: Mutex<Clocks>,
-
-    #[pin]
-    regulators: Mutex<Regulators>,
-
     /// Some information on the GPU.
     ///
     /// This is mainly queried by userspace, i.e.: Mesa.
@@ -101,6 +105,7 @@ impl platform::Driver for TyrPlatformDriver {
     type IdInfo = ();
     type Data<'bound> = TyrPlatformDriverData<'bound>;
     const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
+    const PM_OPS: Option<&'static bindings::dev_pm_ops> = Some(&PMContext::<Self>::PM_OPS);
 
     fn probe<'bound>(
         pdev: &'bound platform::Device<Core<'_>>,
@@ -117,6 +122,25 @@ fn probe<'bound>(
         let mali_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"mali")?;
         let sram_regulator = Regulator::<regulator::Enabled>::get(pdev.as_ref(), c"sram")?;
 
+	let runtime_payload = TyrRuntimePMPayload {
+            clks: Clocks {
+                core: core_clk,
+                stacks: stacks_clk,
+                coregroup: coregroup_clk,
+            },
+            _regulators: Regulators {
+                    _mali: mali_regulator,
+                    _sram: sram_regulator,
+            }
+        };
+
+        let mut pm_configs = KVec::<PMConfig>::with_capacity(2, GFP_KERNEL)?;
+        pm_configs.push(PMConfig::AutoSuspend(true), GFP_KERNEL)?;
+        pm_configs.push(PMConfig::AutoSuspendDelay(300), GFP_KERNEL)?;
+
+        let pm_registration = pm::Registration::new(pdev.as_ref(), None, Some(pm_configs), Some(runtime_payload))?;
+        let pm_context = pm_registration.ctx().clone();
+
         let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;
         let iomem = request.iomap_sized::<SZ_2M>()?;
 
@@ -138,28 +162,26 @@ fn probe<'bound>(
 
         let data = try_pin_init!(TyrDrmDeviceData {
                 pdev: platform.clone(),
-                clks <- new_mutex!(Clocks {
-                    core: core_clk,
-                    stacks: stacks_clk,
-                    coregroup: coregroup_clk,
-                }),
-                regulators <- new_mutex!(Regulators {
-                    _mali: mali_regulator,
-                    _sram: sram_regulator,
-                }),
                 gpu_info,
         });
 
         let tdev = drm::UnregisteredDevice::<TyrDrmDriver>::new(pdev, data)?;
         // SAFETY: `reg` is stored in `TyrPlatformDriverData` and dropped when the driver is
         // unbound; it is never forgotten.
-        let reg = unsafe { drm::Registration::new(pdev.as_ref(), tdev, (), 0)? };
+        let reg = unsafe { drm::Registration::new(
+            pdev.as_ref(),
+            tdev,
+            pin_init!(TyrRuntimePM { pm: pm_context, }),
+            0
+        )? };
 
         let driver = TyrPlatformDriverData {
             _device: reg.device().into(),
             _reg: reg,
+            pm: pm_registration,
         };
 
+        driver.pm.ctx().enable(RuntimePMState::RESUMED)?;
         // We need this to be dev_info!() because dev_dbg!() does not work at
         // all in Rust for now, and we need to see whether probe succeeded.
         dev_info!(pdev, "Tyr initialized correctly.\n");
@@ -185,7 +207,7 @@ fn drop(self: Pin<&mut Self>) {}
 #[vtable]
 impl drm::Driver for TyrDrmDriver {
     type Data = TyrDrmDeviceData;
-    type RegistrationData<'a> = ();
+    type RegistrationData<'a> = TyrRuntimePM<'a>;
     type File = TyrDrmFileData;
     type Object = drm::gem::shmem::Object<BoData>;
     type ParentDevice<Ctx: DeviceContext> = platform::Device<Ctx>;
@@ -216,3 +238,55 @@ struct Regulators {
     _mali: Regulator<regulator::Enabled>,
     _sram: Regulator<regulator::Enabled>,
 }
+
+pub(crate) struct TyrRuntimePMPayload {
+    clks: Clocks,
+    _regulators: Regulators,
+}
+
+#[vtable]
+impl PMOps for TyrPlatformDriver {
+    type DeviceType = platform::Device<kernel::device::Bound>;
+    type RuntimePayloadType = TyrRuntimePMPayload;
+
+    fn runtime_suspend<'a>(
+        _dev: &'a Self::DeviceType,
+        payload: Option<TyrRuntimePMPayload>,
+    ) -> Result<Option<TyrRuntimePMPayload>, (Option<TyrRuntimePMPayload>, Error)>  {
+
+        let Some(payload) = payload else {
+          return Err((None, EINVAL));
+        };
+
+        payload.clks.coregroup.disable_unprepare();
+        payload.clks.stacks.disable_unprepare();
+        payload.clks.core.disable_unprepare();
+        Ok(Some(payload))
+    }
+    fn runtime_resume<'a>(
+        _dev: &'a Self::DeviceType,
+        payload: Option<TyrRuntimePMPayload>,
+    ) -> Result<Option<TyrRuntimePMPayload>, (Option<TyrRuntimePMPayload>, Error)> {
+
+      let Some(payload) = payload else {
+          return Err((None, EINVAL));
+      };
+
+      if let Err(e) = payload.clks.core.prepare_enable() {
+          return Err((Some(payload), e));
+      }
+
+      if let Err(e) = payload.clks.stacks.prepare_enable() {
+          payload.clks.core.disable_unprepare();
+          return Err((Some(payload), e));
+      }
+
+      if let Err(e) = payload.clks.coregroup.prepare_enable() {
+          payload.clks.stacks.disable_unprepare();
+          payload.clks.core.disable_unprepare();
+          return Err((Some(payload), e));
+      }
+
+      Ok(Some(payload))
+   }
+}
diff --git a/drivers/gpu/drm/tyr/file.rs b/drivers/gpu/drm/tyr/file.rs
index b686041d5d6b..d9371ddfb5f3 100644
--- a/drivers/gpu/drm/tyr/file.rs
+++ b/drivers/gpu/drm/tyr/file.rs
@@ -5,6 +5,7 @@
         self,
         Registered, //
     },
+    pm::PMProfile,
     prelude::*,
     uaccess::UserSlice,
     uapi, //
@@ -12,7 +13,8 @@
 
 use crate::driver::{
     TyrDrmDevice,
-    TyrDrmDriver, //
+    TyrDrmDriver,
+    TyrRuntimePM,//
 };
 
 #[pin_data]
@@ -32,10 +34,11 @@ fn open(_dev: &drm::Device<Self::Driver>) -> Result<Pin<KBox<Self>>> {
 impl TyrDrmFileData {
     pub(crate) fn dev_query(
         ddev: &TyrDrmDevice<Registered>,
-        _reg_data: &(),
+        reg_data: &TyrRuntimePM<'_>,
         devquery: &mut uapi::drm_panthor_dev_query,
         _file: &TyrDrmFile,
     ) -> Result<u32> {
+        let _pm_scope = reg_data.pm.get(PMProfile::new())?;
         if devquery.pointer == 0 {
             match devquery.type_ {
                 uapi::drm_panthor_dev_query_type_DRM_PANTHOR_DEV_QUERY_GPU_INFO => {
-- 
2.43.0


  parent reply	other threads:[~2026-07-21 15:37 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-21 15:34 [PATCH v2 0/3] Rust: add runtime PM support Beata Michalska
2026-07-21 15:34 ` [PATCH v2 1/3] rust: " Beata Michalska
2026-07-27 14:56   ` Onur Özkan
2026-07-21 15:34 ` [PATCH v2 2/3] rust: platform: wire runtime PM callbacks Beata Michalska
2026-07-21 15:34 ` Beata Michalska [this message]
2026-07-27 15:00   ` [PATCH v2 3/3] drm/tyr: enable runtime PM Onur Özkan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260721153617.869933-4-beata.michalska@arm.com \
    --to=beata.michalska@arm.com \
    --cc=a.hindborg@kernel.org \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=boris.brezillon@collabora.com \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=driver-core@lists.linux.dev \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rafael@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=samitolvanen@google.com \
    --cc=tmgross@umich.edu \
    --cc=work@onurozkan.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox