From: Karunika Choo Date: Tue, 25 Nov 2025 12:55:45 +0000 (+0000) Subject: drm/panthor: Implement soft reset via PWR_CONTROL X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9ee52f5cdc45e397fddad2a9ed879c72a8fcfa65;p=thirdparty%2Flinux.git 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 Signed-off-by: Karunika Choo Link: https://patch.msgid.link/20251125125548.3282320-6-karunika.choo@arm.com Signed-off-by: Boris Brezillon --- diff --git a/drivers/gpu/drm/panthor/panthor_pwr.c b/drivers/gpu/drm/panthor/panthor_pwr.c index 6dff5daf77d25..57cfc7ce715b8 100644 --- a/drivers/gpu/drm/panthor/panthor_pwr.c +++ b/drivers/gpu/drm/panthor/panthor_pwr.c @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -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 3c834059a860d..adf1f6136abcf 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);