Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Karunika Choo and committed by
Boris Brezillon
9ee52f5c ee4f9af0

+52
+50
drivers/gpu/drm/panthor/panthor_pwr.c
··· 3 3 4 4 #include <linux/platform_device.h> 5 5 #include <linux/interrupt.h> 6 + #include <linux/cleanup.h> 6 7 #include <linux/iopoll.h> 7 8 #include <linux/wait.h> 8 9 ··· 32 31 #define PWR_TRANSITION_TIMEOUT_US (2ULL * USEC_PER_SEC) 33 32 34 33 #define PWR_RETRACT_TIMEOUT_US (2ULL * USEC_PER_MSEC) 34 + 35 + #define PWR_RESET_TIMEOUT_MS 500 35 36 36 37 /** 37 38 * struct panthor_pwr - PWR_CONTROL block management data. ··· 77 74 gpu_write64(ptdev, PWR_CMDARG, args); 78 75 79 76 gpu_write(ptdev, PWR_COMMAND, command); 77 + } 78 + 79 + static bool reset_irq_raised(struct panthor_device *ptdev) 80 + { 81 + return gpu_read(ptdev, PWR_INT_RAWSTAT) & PWR_IRQ_RESET_COMPLETED; 82 + } 83 + 84 + static bool reset_pending(struct panthor_device *ptdev) 85 + { 86 + return (ptdev->pwr->pending_reqs & PWR_IRQ_RESET_COMPLETED); 87 + } 88 + 89 + static int panthor_pwr_reset(struct panthor_device *ptdev, u32 reset_cmd) 90 + { 91 + scoped_guard(spinlock_irqsave, &ptdev->pwr->reqs_lock) { 92 + if (reset_pending(ptdev)) { 93 + drm_WARN(&ptdev->base, 1, "Reset already pending"); 94 + } else { 95 + ptdev->pwr->pending_reqs |= PWR_IRQ_RESET_COMPLETED; 96 + gpu_write(ptdev, PWR_INT_CLEAR, PWR_IRQ_RESET_COMPLETED); 97 + panthor_pwr_write_command(ptdev, reset_cmd, 0); 98 + } 99 + } 100 + 101 + if (!wait_event_timeout(ptdev->pwr->reqs_acked, !reset_pending(ptdev), 102 + msecs_to_jiffies(PWR_RESET_TIMEOUT_MS))) { 103 + guard(spinlock_irqsave)(&ptdev->pwr->reqs_lock); 104 + 105 + if (reset_pending(ptdev) && !reset_irq_raised(ptdev)) { 106 + drm_err(&ptdev->base, "RESET timed out (0x%x)", reset_cmd); 107 + return -ETIMEDOUT; 108 + } 109 + 110 + ptdev->pwr->pending_reqs &= ~PWR_IRQ_RESET_COMPLETED; 111 + } 112 + 113 + return 0; 80 114 } 81 115 82 116 static const char *get_domain_name(u8 domain) ··· 467 427 return err; 468 428 469 429 return 0; 430 + } 431 + 432 + int panthor_pwr_reset_soft(struct panthor_device *ptdev) 433 + { 434 + if (!(gpu_read64(ptdev, PWR_STATUS) & PWR_STATUS_ALLOW_SOFT_RESET)) { 435 + drm_err(&ptdev->base, "RESET_SOFT not allowed"); 436 + return -EOPNOTSUPP; 437 + } 438 + 439 + return panthor_pwr_reset(ptdev, PWR_COMMAND_RESET_SOFT); 470 440 } 471 441 472 442 void panthor_pwr_l2_power_off(struct panthor_device *ptdev)
+2
drivers/gpu/drm/panthor/panthor_pwr.h
··· 10 10 11 11 int panthor_pwr_init(struct panthor_device *ptdev); 12 12 13 + int panthor_pwr_reset_soft(struct panthor_device *ptdev); 14 + 13 15 void panthor_pwr_l2_power_off(struct panthor_device *ptdev); 14 16 15 17 int panthor_pwr_l2_power_on(struct panthor_device *ptdev);