[RFC PATCH 3/3] [DO NOT MERGE] drm/tyr: wire runtime PM hooks
From: Beata Michalska
Date: Thu May 14 2026 - 11:22:52 EST
Add support for runtime PM.
Apply basic configuration and add suspend/resume hooks, ready for
future power-gating support.
Signed-off-by: Beata Michalska <beata.michalska@xxxxxxx>
---
drivers/gpu/drm/tyr/driver.rs | 123 +++++++++++++++++++++++++++-------
drivers/gpu/drm/tyr/file.rs | 3 +
2 files changed, 103 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/tyr/driver.rs b/drivers/gpu/drm/tyr/driver.rs
index 279710b36a10..cda3b7bcd352 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, //
@@ -17,6 +18,7 @@
new_mutex,
of,
platform,
+ pm::*,
prelude::*,
regulator,
regulator::Regulator,
@@ -53,12 +55,12 @@ pub(crate) struct TyrPlatformDriverData {
pub(crate) struct TyrDrmDeviceData {
pub(crate) pdev: ARef<platform::Device>,
- #[pin]
- clks: Mutex<Clocks>,
-
#[pin]
regulators: Mutex<Regulators>,
+ /// Runtime PM context
+ pub(crate) pm_context: PMContext<TyrPlatformDriverData, kernel::pm::Active>,
+
/// Some information on the GPU.
///
/// This is mainly queried by userspace, i.e.: Mesa.
@@ -92,25 +94,23 @@ fn issue_soft_reset(dev: &Device<Bound>, iomem: &Devres<IoMem>) -> Result {
impl platform::Driver for TyrPlatformDriverData {
type IdInfo = ();
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(
pdev: &platform::Device<Core>,
_info: Option<&Self::IdInfo>,
) -> impl PinInit<Self, Error> {
- let core_clk = Clk::get(pdev.as_ref(), Some(c"core"))?;
- let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c"stacks"))?;
- let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c"coregroup"))?;
-
- core_clk.prepare_enable()?;
- stacks_clk.prepare_enable()?;
- coregroup_clk.prepare_enable()?;
-
+ let pm_state = TyrRuntimeState::pm_init(pdev.as_ref())?;
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 request = pdev.io_request_by_index(0).ok_or(ENODEV)?;
let iomem = Arc::pin_init(request.iomap_sized::<SZ_2M>(), GFP_KERNEL)?;
+ let pm_context = PMContext::new(pdev.as_ref(), None)?;
+ pm_context.apply_config(&[PMConfig::AutoSuspend(true),PMConfig::AutoSuspendDelay(300)])?;
+ pm_context.init_state(RuntimePMState::Active, Some(pm_state))?;
+
issue_soft_reset(pdev.as_ref(), &iomem)?;
gpu::l2_power_on(pdev.as_ref(), &iomem)?;
@@ -121,15 +121,11 @@ fn probe(
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,
}),
+ pm_context: pm_context.enable()?,
gpu_info,
});
@@ -152,13 +148,7 @@ fn drop(self: Pin<&mut Self>) {}
#[pinned_drop]
impl PinnedDrop for TyrDrmDeviceData {
- fn drop(self: Pin<&mut Self>) {
- // TODO: the type-state pattern for Clks will fix this.
- let clks = self.clks.lock();
- clks.core.disable_unprepare();
- clks.stacks.disable_unprepare();
- clks.coregroup.disable_unprepare();
- }
+ fn drop(self: Pin<&mut Self>) {}
}
// We need to retain the name "panthor" to achieve drop-in compatibility with
@@ -196,3 +186,90 @@ struct Regulators {
_mali: Regulator<regulator::Enabled>,
_sram: Regulator<regulator::Enabled>,
}
+
+pub(crate) struct TyrRuntimeState {
+ clks: Clocks,
+}
+
+impl TyrRuntimeState {
+ fn pm_init(dev: &'_ kernel::device::Device<kernel::device::Bound>) -> Result<Arc<Self>> {
+ let core_clk = Clk::get(dev, Some(c"core"))?;
+ let stacks_clk = OptionalClk::get(dev, Some(c"stacks"))?;
+ let coregroup_clk = OptionalClk::get(dev, Some(c"coregroup"))?;
+
+ core_clk.prepare_enable()?;
+ stacks_clk.prepare_enable()?;
+ coregroup_clk.prepare_enable()?;
+
+ Ok(Arc::new(
+ Self {
+ clks: Clocks {
+ core: core_clk,
+ stacks: stacks_clk,
+ coregroup: coregroup_clk,
+ }
+ },
+ GFP_KERNEL
+ )?)
+ }
+}
+
+#[vtable]
+impl PMOps for TyrPlatformDriverData {
+ type DriverDataType = TyrPlatformDriverData;
+ type DeviceType<'a> = &'a platform::Device;
+ type RuntimePayloadType = TyrRuntimeState;
+ type PMContextRef<'a> = &'a PMContext<TyrPlatformDriverData, Active>;
+
+ fn get_pmcontext(data: &Self::DriverDataType) -> Result<Self::PMContextRef<'_>> {
+ Ok(&data._device.pm_context)
+ }
+
+ fn runtime_suspend(
+ _dev: Self::DeviceType<'_>,
+ data: Option<Arc<Self::RuntimePayloadType>>
+ ) -> Result<
+ Option<Arc<Self::RuntimePayloadType>>,
+ (Option<Arc<Self::RuntimePayloadType>>, kernel::error::Error)
+ > {
+ match data {
+ Some(state) => {
+ state.clks.core.disable_unprepare();
+ state.clks.stacks.disable_unprepare();
+ state.clks.coregroup.disable_unprepare();
+
+ Ok(Some(state))
+ }
+ None => {
+ pr_err!("Tyr: no runtime data\n");
+ Ok(None)
+ }
+ }
+ }
+
+ fn runtime_resume(
+ _dev: Self::DeviceType<'_>,
+ data: Option<Arc<Self::RuntimePayloadType>>
+ ) -> Result<
+ Option<Arc<Self::RuntimePayloadType>>,
+ (Option<Arc<Self::RuntimePayloadType>>, kernel::error::Error)
+ > {
+
+ match data {
+ Some(state) => {
+ let previous_state = Some(state.clone());
+ (|| {
+ //@TODO: @FIXME: this needs to be able to unroll changes
+ state.clks.core.prepare_enable()?;
+ state.clks.stacks.prepare_enable()?;
+ state.clks.coregroup.prepare_enable()?;
+
+ Ok(Some(state))
+ }
+ )()
+ .map_err(|e| (previous_state, e))
+ },
+ None => Err((data, EINVAL)),
+ }
+ }
+}
diff --git a/drivers/gpu/drm/tyr/file.rs b/drivers/gpu/drm/tyr/file.rs
index 31411da203c5..8256ce05fb6f 100644
--- a/drivers/gpu/drm/tyr/file.rs
+++ b/drivers/gpu/drm/tyr/file.rs
@@ -2,6 +2,7 @@
use kernel::{
drm,
+ pm::*,
prelude::*,
uaccess::UserSlice,
uapi, //
@@ -32,6 +33,8 @@ pub(crate) fn dev_query(
devquery: &mut uapi::drm_panthor_dev_query,
_file: &TyrDrmFile,
) -> Result<u32> {
+ let _pm_scope = ddev.pm_context.get(Profile::new())?;
+
if devquery.pointer == 0 {
match devquery.type_ {
uapi::drm_panthor_dev_query_type_DRM_PANTHOR_DEV_QUERY_GPU_INFO => {
--
2.43.0