diff options
| author | Karunika Choo <karunika.choo@arm.com> | 2025-11-25 12:55:45 +0000 |
|---|---|---|
| committer | Boris Brezillon <boris.brezillon@collabora.com> | 2025-11-26 10:56:19 +0100 |
| commit | 9ee52f5cdc45e397fddad2a9ed879c72a8fcfa65 (patch) | |
| tree | b6060b4b1ea2ce20598609c44a3283e67937dd36 /drivers/gpu/drm/panthor | |
| parent | ee4f9af07933648f2f9337d7b24da5562a594399 (diff) | |
drm/panthor: Implement soft reset via PWR_CONTROL
Add helpers to issue reset commands through the PWR_CONTROL interface
and wait for reset completion using IRQ signaling. This enables support
for RESET_SOFT operations with timeout handling and status verification.
Reviewed-by: Steven Price <steven.price@arm.com>
Signed-off-by: Karunika Choo <karunika.choo@arm.com>
Link: https://patch.msgid.link/20251125125548.3282320-6-karunika.choo@arm.com
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Diffstat (limited to 'drivers/gpu/drm/panthor')
| -rw-r--r-- | drivers/gpu/drm/panthor/panthor_pwr.c | 50 | ||||
| -rw-r--r-- | drivers/gpu/drm/panthor/panthor_pwr.h | 2 |
2 files changed, 52 insertions, 0 deletions
diff --git a/drivers/gpu/drm/panthor/panthor_pwr.c b/drivers/gpu/drm/panthor/panthor_pwr.c index 6dff5daf77d2..57cfc7ce715b 100644 --- a/drivers/gpu/drm/panthor/panthor_pwr.c +++ b/drivers/gpu/drm/panthor/panthor_pwr.c @@ -3,6 +3,7 @@ #include <linux/platform_device.h> #include <linux/interrupt.h> +#include <linux/cleanup.h> #include <linux/iopoll.h> #include <linux/wait.h> @@ -32,6 +33,8 @@ #define PWR_RETRACT_TIMEOUT_US (2ULL * USEC_PER_MSEC) +#define PWR_RESET_TIMEOUT_MS 500 + /** * struct panthor_pwr - PWR_CONTROL block management data. */ @@ -76,6 +79,43 @@ static void panthor_pwr_write_command(struct panthor_device *ptdev, u32 command, gpu_write(ptdev, PWR_COMMAND, command); } +static bool reset_irq_raised(struct panthor_device *ptdev) +{ + return gpu_read(ptdev, PWR_INT_RAWSTAT) & PWR_IRQ_RESET_COMPLETED; +} + +static bool reset_pending(struct panthor_device *ptdev) +{ + return (ptdev->pwr->pending_reqs & PWR_IRQ_RESET_COMPLETED); +} + +static int panthor_pwr_reset(struct panthor_device *ptdev, u32 reset_cmd) +{ + scoped_guard(spinlock_irqsave, &ptdev->pwr->reqs_lock) { + if (reset_pending(ptdev)) { + drm_WARN(&ptdev->base, 1, "Reset already pending"); + } else { + ptdev->pwr->pending_reqs |= PWR_IRQ_RESET_COMPLETED; + gpu_write(ptdev, PWR_INT_CLEAR, PWR_IRQ_RESET_COMPLETED); + panthor_pwr_write_command(ptdev, reset_cmd, 0); + } + } + + if (!wait_event_timeout(ptdev->pwr->reqs_acked, !reset_pending(ptdev), + msecs_to_jiffies(PWR_RESET_TIMEOUT_MS))) { + guard(spinlock_irqsave)(&ptdev->pwr->reqs_lock); + + if (reset_pending(ptdev) && !reset_irq_raised(ptdev)) { + drm_err(&ptdev->base, "RESET timed out (0x%x)", reset_cmd); + return -ETIMEDOUT; + } + + ptdev->pwr->pending_reqs &= ~PWR_IRQ_RESET_COMPLETED; + } + + return 0; +} + static const char *get_domain_name(u8 domain) { switch (domain) { @@ -429,6 +469,16 @@ int panthor_pwr_init(struct panthor_device *ptdev) return 0; } +int panthor_pwr_reset_soft(struct panthor_device *ptdev) +{ + if (!(gpu_read64(ptdev, PWR_STATUS) & PWR_STATUS_ALLOW_SOFT_RESET)) { + drm_err(&ptdev->base, "RESET_SOFT not allowed"); + return -EOPNOTSUPP; + } + + return panthor_pwr_reset(ptdev, PWR_COMMAND_RESET_SOFT); +} + void panthor_pwr_l2_power_off(struct panthor_device *ptdev) { const u64 l2_allow_mask = PWR_STATUS_DOMAIN_ALLOWED(PWR_COMMAND_DOMAIN_L2); diff --git a/drivers/gpu/drm/panthor/panthor_pwr.h b/drivers/gpu/drm/panthor/panthor_pwr.h index 3c834059a860..adf1f6136abc 100644 --- a/drivers/gpu/drm/panthor/panthor_pwr.h +++ b/drivers/gpu/drm/panthor/panthor_pwr.h @@ -10,6 +10,8 @@ void panthor_pwr_unplug(struct panthor_device *ptdev); int panthor_pwr_init(struct panthor_device *ptdev); +int panthor_pwr_reset_soft(struct panthor_device *ptdev); + void panthor_pwr_l2_power_off(struct panthor_device *ptdev); int panthor_pwr_l2_power_on(struct panthor_device *ptdev); |