linux/drivers/gpu/drm/imagination/pvr_power.h
Michal Wilczynski e38e8391f3
drm/imagination: Use pwrseq for TH1520 GPU power management
Update the Imagination PVR DRM driver to leverage the pwrseq framework
for managing the complex power sequence of the GPU on the T-HEAD TH1520
SoC.

To cleanly separate platform-specific logic from the generic driver,
this patch introduces an `init` callback to the `pwr_power_sequence_ops`
struct. This allows for different power management strategies to be
selected at probe time based on the device's compatible string.

A `pvr_device_data` struct, associated with each compatible in the
of_device_id table, points to the appropriate ops table (manual or
pwrseq).

At probe time, the driver now calls the `->init()` op. For pwrseq-based
platforms, this callback calls `devm_pwrseq_get("gpu-power")`, deferring
probe if the sequencer is not yet available. For other platforms, it
falls back to the existing manual clock and reset handling. The runtime
PM callbacks continue to call the appropriate functions via the ops
table.

Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Matt Coster <matt.coster@imgtec.com>
Link: https://lore.kernel.org/r/20250822-apr_14_for_sending-v13-1-af656f7cc6c3@samsung.com
Signed-off-by: Matt Coster <matt.coster@imgtec.com>
2025-09-01 12:11:00 +01:00

59 lines
1.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
/* Copyright (c) 2023 Imagination Technologies Ltd. */
#ifndef PVR_POWER_H
#define PVR_POWER_H
#include "pvr_device.h"
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
int pvr_watchdog_init(struct pvr_device *pvr_dev);
void pvr_watchdog_fini(struct pvr_device *pvr_dev);
void pvr_device_lost(struct pvr_device *pvr_dev);
bool pvr_power_is_idle(struct pvr_device *pvr_dev);
int pvr_power_device_suspend(struct device *dev);
int pvr_power_device_resume(struct device *dev);
int pvr_power_device_idle(struct device *dev);
int pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset);
static __always_inline int
pvr_power_get(struct pvr_device *pvr_dev)
{
struct drm_device *drm_dev = from_pvr_device(pvr_dev);
return pm_runtime_resume_and_get(drm_dev->dev);
}
static __always_inline int
pvr_power_put(struct pvr_device *pvr_dev)
{
struct drm_device *drm_dev = from_pvr_device(pvr_dev);
return pm_runtime_put(drm_dev->dev);
}
int pvr_power_domains_init(struct pvr_device *pvr_dev);
void pvr_power_domains_fini(struct pvr_device *pvr_dev);
/**
* struct pvr_power_sequence_ops - Platform specific power sequence operations.
* @init: Pointer to the platform-specific initialization function.
* @power_on: Pointer to the platform-specific power on function.
* @power_off: Pointer to the platform-specific power off function.
*/
struct pvr_power_sequence_ops {
int (*init)(struct pvr_device *pvr_dev);
int (*power_on)(struct pvr_device *pvr_dev);
int (*power_off)(struct pvr_device *pvr_dev);
};
extern const struct pvr_power_sequence_ops pvr_power_sequence_ops_manual;
extern const struct pvr_power_sequence_ops pvr_power_sequence_ops_pwrseq;
#endif /* PVR_POWER_H */