[RFC PATCH 3/4] drm/panthor: Add gpu specific initialization framework

Karunika Choo posted 4 patches 12 months ago
[RFC PATCH 3/4] drm/panthor: Add gpu specific initialization framework
Posted by Karunika Choo 12 months ago
This patch adds a framework for adding GPU specific code which adds the
following gpu-specific features:
- register base addresses
- feature bits
- function pointers

The above allows the handling of changes to register and register set
offsets, as well as logical changes to the code between GPUs.

Signed-off-by: Karunika Choo <karunika.choo@arm.com>
---
 drivers/gpu/drm/panthor/Makefile         |  1 +
 drivers/gpu/drm/panthor/panthor_device.c | 22 ++++--
 drivers/gpu/drm/panthor/panthor_device.h | 28 +++++--
 drivers/gpu/drm/panthor/panthor_fw.c     | 27 ++++---
 drivers/gpu/drm/panthor/panthor_gpu.c    | 44 ++++++-----
 drivers/gpu/drm/panthor/panthor_gpu.h    |  1 +
 drivers/gpu/drm/panthor/panthor_hw.c     | 94 ++++++++++++++++++++++++
 drivers/gpu/drm/panthor/panthor_hw.h     | 92 +++++++++++++++++++++++
 drivers/gpu/drm/panthor/panthor_mmu.c    | 41 ++++++-----
 drivers/gpu/drm/panthor/panthor_regs.h   | 62 ++++++++--------
 drivers/gpu/drm/panthor/panthor_sched.c  |  1 +
 11 files changed, 323 insertions(+), 90 deletions(-)
 create mode 100644 drivers/gpu/drm/panthor/panthor_hw.c
 create mode 100644 drivers/gpu/drm/panthor/panthor_hw.h

diff --git a/drivers/gpu/drm/panthor/Makefile b/drivers/gpu/drm/panthor/Makefile
index ab297637d172..e1f06396bd1d 100644
--- a/drivers/gpu/drm/panthor/Makefile
+++ b/drivers/gpu/drm/panthor/Makefile
@@ -8,6 +8,7 @@ panthor-y := \
 	panthor_gem.o \
 	panthor_gpu.o \
 	panthor_heap.o \
+	panthor_hw.o \
 	panthor_mmu.o \
 	panthor_props.o \
 	panthor_sched.o
diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
index 0b74dc628489..fd261e525b7b 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -18,6 +18,7 @@
 #include "panthor_device.h"
 #include "panthor_fw.h"
 #include "panthor_gpu.h"
+#include "panthor_hw.h"
 #include "panthor_mmu.h"
 #include "panthor_props.h"
 #include "panthor_regs.h"
@@ -116,6 +117,11 @@ void panthor_device_unplug(struct panthor_device *ptdev)
 	complete_all(&ptdev->unplug.done);
 }
 
+static bool panthor_device_is_initialized(struct panthor_device *ptdev)
+{
+	return !!ptdev->scheduler;
+}
+
 static void panthor_device_reset_cleanup(struct drm_device *ddev, void *data)
 {
 	struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base);
@@ -141,11 +147,14 @@ static void panthor_device_reset_work(struct work_struct *work)
 	if (!drm_dev_enter(&ptdev->base, &cookie))
 		return;
 
+	if (!panthor_device_is_initialized(ptdev))
+		return;
+
 	panthor_sched_pre_reset(ptdev);
 	panthor_fw_pre_reset(ptdev, true);
 	panthor_mmu_pre_reset(ptdev);
-	panthor_gpu_soft_reset(ptdev);
-	panthor_gpu_l2_power_on(ptdev);
+	ptdev->hw->ops.soft_reset(ptdev);
+	ptdev->hw->ops.l2_power_on(ptdev);
 	panthor_mmu_post_reset(ptdev);
 	ret = panthor_fw_post_reset(ptdev);
 	atomic_set(&ptdev->reset.pending, 0);
@@ -158,11 +167,6 @@ static void panthor_device_reset_work(struct work_struct *work)
 	}
 }
 
-static bool panthor_device_is_initialized(struct panthor_device *ptdev)
-{
-	return !!ptdev->scheduler;
-}
-
 static void panthor_device_free_page(struct drm_device *ddev, void *data)
 {
 	__free_page(data);
@@ -247,6 +251,10 @@ int panthor_device_init(struct panthor_device *ptdev)
 			return ret;
 	}
 
+	ret = panthor_hw_init(ptdev);
+	if (ret)
+		goto err_rpm_put;
+
 	ret = panthor_gpu_init(ptdev);
 	if (ret)
 		goto err_rpm_put;
diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
index 60c9a67fb4a2..a984d5f9a68a 100644
--- a/drivers/gpu/drm/panthor/panthor_device.h
+++ b/drivers/gpu/drm/panthor/panthor_device.h
@@ -24,6 +24,7 @@ struct panthor_device;
 struct panthor_gpu;
 struct panthor_group_pool;
 struct panthor_heap_pool;
+struct panthor_hw;
 struct panthor_job;
 struct panthor_mmu;
 struct panthor_props;
@@ -124,6 +125,9 @@ struct panthor_device {
 	/** @csif_info: Command stream interface information. */
 	struct drm_panthor_csif_info csif_info;
 
+	/** @hw: GPU specific data */
+	struct panthor_hw *hw;
+
 	/** @gpu: GPU management data. */
 	struct panthor_gpu *gpu;
 
@@ -365,13 +369,14 @@ static irqreturn_t panthor_ ## __name ## _irq_raw_handler(int irq, void *data)
 {												\
 	struct panthor_irq *pirq = data;							\
 	struct panthor_device *ptdev = pirq->ptdev;						\
+	const u64 base = ptdev->hw->map.__name ## _irq.base;					\
 												\
 	if (atomic_read(&pirq->suspended))							\
 		return IRQ_NONE;								\
-	if (!gpu_read(ptdev, __reg_prefix ## _INT_STAT))					\
+	if (!gpu_read(ptdev, base + __reg_prefix ## _INT_STAT))					\
 		return IRQ_NONE;								\
 												\
-	gpu_write(ptdev, __reg_prefix ## _INT_MASK, 0);						\
+	gpu_write(ptdev, base + __reg_prefix ## _INT_MASK, 0);					\
 	return IRQ_WAKE_THREAD;									\
 }												\
 												\
@@ -379,40 +384,47 @@ static irqreturn_t panthor_ ## __name ## _irq_threaded_handler(int irq, void *da
 {												\
 	struct panthor_irq *pirq = data;							\
 	struct panthor_device *ptdev = pirq->ptdev;						\
+	const u64 base = ptdev->hw->map.__name ## _irq.base;					\
 	irqreturn_t ret = IRQ_NONE;								\
 												\
 	while (true) {										\
-		u32 status = gpu_read(ptdev, __reg_prefix ## _INT_RAWSTAT) & pirq->mask;	\
+		u32 status = gpu_read(ptdev, base + __reg_prefix ## _INT_RAWSTAT) & pirq->mask;	\
 												\
 		if (!status)									\
 			break;									\
 												\
-		gpu_write(ptdev, __reg_prefix ## _INT_CLEAR, status);				\
+		gpu_write(ptdev, base + __reg_prefix ## _INT_CLEAR, status);			\
 												\
 		__handler(ptdev, status);							\
 		ret = IRQ_HANDLED;								\
 	}											\
 												\
 	if (!atomic_read(&pirq->suspended))							\
-		gpu_write(ptdev, __reg_prefix ## _INT_MASK, pirq->mask);			\
+		gpu_write(ptdev, base + __reg_prefix ## _INT_MASK, pirq->mask);			\
 												\
 	return ret;										\
 }												\
 												\
 static inline void panthor_ ## __name ## _irq_suspend(struct panthor_irq *pirq)			\
 {												\
+	struct panthor_device *ptdev = pirq->ptdev;						\
+	const u64 base = ptdev->hw->map.__name ## _irq.base;					\
+												\
 	pirq->mask = 0;										\
-	gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, 0);					\
+	gpu_write(pirq->ptdev, base + __reg_prefix ## _INT_MASK, 0);				\
 	synchronize_irq(pirq->irq);								\
 	atomic_set(&pirq->suspended, true);							\
 }												\
 												\
 static inline void panthor_ ## __name ## _irq_resume(struct panthor_irq *pirq, u32 mask)	\
 {												\
+	struct panthor_device *ptdev = pirq->ptdev;						\
+	const u64 base = ptdev->hw->map.__name ## _irq.base;					\
+												\
 	atomic_set(&pirq->suspended, false);							\
 	pirq->mask = mask;									\
-	gpu_write(pirq->ptdev, __reg_prefix ## _INT_CLEAR, mask);				\
-	gpu_write(pirq->ptdev, __reg_prefix ## _INT_MASK, mask);				\
+	gpu_write(pirq->ptdev, base + __reg_prefix ## _INT_CLEAR, mask);			\
+	gpu_write(pirq->ptdev, base + __reg_prefix ## _INT_MASK, mask);				\
 }												\
 												\
 static int panthor_request_ ## __name ## _irq(struct panthor_device *ptdev,			\
diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c
index 51b63d258c7a..27c2e950927b 100644
--- a/drivers/gpu/drm/panthor/panthor_fw.c
+++ b/drivers/gpu/drm/panthor/panthor_fw.c
@@ -21,6 +21,7 @@
 #include "panthor_fw.h"
 #include "panthor_gem.h"
 #include "panthor_gpu.h"
+#include "panthor_hw.h"
 #include "panthor_mmu.h"
 #include "panthor_props.h"
 #include "panthor_regs.h"
@@ -34,6 +35,9 @@
 #define IDLE_HYSTERESIS_US			800
 #define PWROFF_HYSTERESIS_US			10000
 
+#define MCU_BASE(ptdev) (ptdev->hw->map.mcu_control_base)
+#define JOB_BASE(ptdev) (ptdev->hw->map.job_irq.base)
+
 /**
  * struct panthor_fw_binary_hdr - Firmware binary header.
  */
@@ -1030,13 +1034,13 @@ static int panthor_fw_start(struct panthor_device *ptdev)
 
 	ptdev->fw->booted = false;
 	panthor_job_irq_resume(&ptdev->fw->irq, ~0);
-	gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_AUTO);
+	gpu_write(ptdev, MCU_BASE(ptdev) + MCU_CONTROL, MCU_CONTROL_AUTO);
 
 	if (!wait_event_timeout(ptdev->fw->req_waitqueue,
 				ptdev->fw->booted,
 				msecs_to_jiffies(1000))) {
 		if (!ptdev->fw->booted &&
-		    !(gpu_read(ptdev, JOB_INT_STAT) & JOB_INT_GLOBAL_IF))
+		    !(gpu_read(ptdev, JOB_BASE(ptdev) + JOB_INT_STAT) & JOB_INT_GLOBAL_IF))
 			timedout = true;
 	}
 
@@ -1047,7 +1051,7 @@ static int panthor_fw_start(struct panthor_device *ptdev)
 			[MCU_STATUS_HALT] = "halt",
 			[MCU_STATUS_FATAL] = "fatal",
 		};
-		u32 status = gpu_read(ptdev, MCU_STATUS);
+		u32 status = gpu_read(ptdev, MCU_BASE(ptdev) + MCU_STATUS);
 
 		drm_err(&ptdev->base, "Failed to boot MCU (status=%s)",
 			status < ARRAY_SIZE(status_str) ? status_str[status] : "unknown");
@@ -1061,8 +1065,8 @@ static void panthor_fw_stop(struct panthor_device *ptdev)
 {
 	u32 status;
 
-	gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_DISABLE);
-	if (gpu_read_poll_timeout(ptdev, MCU_STATUS, status,
+	gpu_write(ptdev, MCU_BASE(ptdev) + MCU_CONTROL, MCU_CONTROL_DISABLE);
+	if (gpu_read_poll_timeout(ptdev, MCU_BASE(ptdev) + MCU_STATUS, status,
 				  status == MCU_STATUS_DISABLED, 10, 100000))
 		drm_err(&ptdev->base, "Failed to stop MCU");
 }
@@ -1088,10 +1092,10 @@ void panthor_fw_pre_reset(struct panthor_device *ptdev, bool on_hang)
 
 		panthor_fw_update_reqs(glb_iface, req, GLB_HALT, GLB_HALT);
 		gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1);
-		if (!gpu_read_poll_timeout(ptdev, MCU_STATUS, status,
-					   status == MCU_STATUS_HALT, 10,
-					   100000)) {
-			ptdev->fw->fast_reset = true;
+		if (!gpu_read_poll_timeout(ptdev, MCU_BASE(ptdev) + MCU_STATUS,
+					   status, status == MCU_STATUS_HALT,
+					   10, 100000)) {
+			ptdev->reset.fast = true;
 		} else {
 			drm_warn(&ptdev->base, "Failed to cleanly suspend MCU");
 		}
@@ -1183,7 +1187,7 @@ void panthor_fw_unplug(struct panthor_device *ptdev)
 	ptdev->fw->vm = NULL;
 
 	if (!IS_ENABLED(CONFIG_PM) || pm_runtime_active(ptdev->base.dev))
-		panthor_gpu_power_off(ptdev, L2, ptdev->gpu_info.l2_present, 20000);
+		ptdev->hw->ops.l2_power_off(ptdev);
 }
 
 /**
@@ -1352,7 +1356,8 @@ int panthor_fw_init(struct panthor_device *ptdev)
 	INIT_LIST_HEAD(&fw->sections);
 	INIT_DELAYED_WORK(&fw->watchdog.ping_work, panthor_fw_ping_work);
 
-	irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "job");
+	irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev),
+				      ptdev->hw->map.job_irq.name);
 	if (irq <= 0)
 		return -ENODEV;
 
diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c
index ec1780fe2638..9dadcea67a39 100644
--- a/drivers/gpu/drm/panthor/panthor_gpu.c
+++ b/drivers/gpu/drm/panthor/panthor_gpu.c
@@ -18,9 +18,12 @@
 
 #include "panthor_device.h"
 #include "panthor_gpu.h"
+#include "panthor_hw.h"
 #include "panthor_props.h"
 #include "panthor_regs.h"
 
+#define GPU_BASE(ptdev) (ptdev->hw->map.gpu_control_base)
+
 /**
  * struct panthor_gpu - GPU block management data.
  */
@@ -46,15 +49,15 @@ struct panthor_gpu {
 
 static void panthor_gpu_coherency_set(struct panthor_device *ptdev)
 {
-	gpu_write(ptdev, GPU_COHERENCY_PROTOCOL,
+	gpu_write(ptdev, GPU_BASE(ptdev) + GPU_COHERENCY_PROTOCOL,
 		ptdev->coherent ? GPU_COHERENCY_PROT_BIT(ACE_LITE) : GPU_COHERENCY_NONE);
 }
 
 static void panthor_gpu_irq_handler(struct panthor_device *ptdev, u32 status)
 {
 	if (status & GPU_IRQ_FAULT) {
-		u32 fault_status = gpu_read(ptdev, GPU_FAULT_STATUS);
-		u64 address = gpu_read64(ptdev, GPU_FAULT_ADDR_LO);
+		u32 fault_status = gpu_read(ptdev, GPU_BASE(ptdev) + GPU_FAULT_STATUS);
+		u64 address = gpu_read64(ptdev, GPU_BASE(ptdev) + GPU_FAULT_ADDR_LO);
 
 		drm_warn(&ptdev->base, "GPU Fault 0x%08x (%s) at 0x%016llx\n",
 			 fault_status, panthor_exception_name(ptdev, fault_status & 0xFF),
@@ -110,17 +113,14 @@ int panthor_gpu_init(struct panthor_device *ptdev)
 	init_waitqueue_head(&gpu->reqs_acked);
 	ptdev->gpu = gpu;
 
-	ret = panthor_props_init(ptdev);
-	if (ret)
-		return ret;
-
 	dma_set_max_seg_size(ptdev->base.dev, UINT_MAX);
 	ret = dma_set_mask_and_coherent(ptdev->base.dev,
 					DMA_BIT_MASK(ptdev->props->mmu_pa_bits));
 	if (ret)
 		return ret;
 
-	irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "gpu");
+	irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev),
+				      ptdev->hw->map.gpu_irq.name);
 	if (irq < 0)
 		return irq;
 
@@ -216,6 +216,12 @@ int panthor_gpu_block_power_on(struct panthor_device *ptdev,
 	return 0;
 }
 
+int panthor_gpu_l2_power_off(struct panthor_device *ptdev)
+{
+	return panthor_gpu_power_off(ptdev, L2, ptdev->gpu_info.l2_present,
+				     20000);
+}
+
 /**
  * panthor_gpu_l2_power_on() - Power-on the L2-cache
  * @ptdev: Device.
@@ -264,7 +270,7 @@ int panthor_gpu_flush_caches(struct panthor_device *ptdev,
 	if (!drm_WARN_ON(&ptdev->base,
 			 ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED)) {
 		ptdev->gpu->pending_reqs |= GPU_IRQ_CLEAN_CACHES_COMPLETED;
-		gpu_write(ptdev, GPU_CMD, GPU_FLUSH_CACHES(l2, lsc, other));
+		gpu_write(ptdev, GPU_BASE(ptdev) + GPU_CMD, GPU_FLUSH_CACHES(l2, lsc, other));
 	}
 	spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags);
 
@@ -272,8 +278,10 @@ int panthor_gpu_flush_caches(struct panthor_device *ptdev,
 				!(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED),
 				msecs_to_jiffies(100))) {
 		spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);
-		if ((ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED) != 0 &&
-		    !(gpu_read(ptdev, GPU_INT_RAWSTAT) & GPU_IRQ_CLEAN_CACHES_COMPLETED))
+		if ((ptdev->gpu->pending_reqs &
+		     GPU_IRQ_CLEAN_CACHES_COMPLETED) != 0 &&
+		    !(gpu_read(ptdev, GPU_BASE(ptdev) + GPU_INT_RAWSTAT) &
+		      GPU_IRQ_CLEAN_CACHES_COMPLETED))
 			timedout = true;
 		else
 			ptdev->gpu->pending_reqs &= ~GPU_IRQ_CLEAN_CACHES_COMPLETED;
@@ -303,8 +311,8 @@ int panthor_gpu_soft_reset(struct panthor_device *ptdev)
 	if (!drm_WARN_ON(&ptdev->base,
 			 ptdev->gpu->pending_reqs & GPU_IRQ_RESET_COMPLETED)) {
 		ptdev->gpu->pending_reqs |= GPU_IRQ_RESET_COMPLETED;
-		gpu_write(ptdev, GPU_INT_CLEAR, GPU_IRQ_RESET_COMPLETED);
-		gpu_write(ptdev, GPU_CMD, GPU_SOFT_RESET);
+		gpu_write(ptdev, GPU_BASE(ptdev) + GPU_INT_CLEAR, GPU_IRQ_RESET_COMPLETED);
+		gpu_write(ptdev, GPU_BASE(ptdev) + GPU_CMD, GPU_SOFT_RESET);
 	}
 	spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags);
 
@@ -313,7 +321,7 @@ int panthor_gpu_soft_reset(struct panthor_device *ptdev)
 				msecs_to_jiffies(100))) {
 		spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);
 		if ((ptdev->gpu->pending_reqs & GPU_IRQ_RESET_COMPLETED) != 0 &&
-		    !(gpu_read(ptdev, GPU_INT_RAWSTAT) & GPU_IRQ_RESET_COMPLETED))
+		    !(gpu_read(ptdev, GPU_BASE(ptdev) + GPU_INT_RAWSTAT) & GPU_IRQ_RESET_COMPLETED))
 			timedout = true;
 		else
 			ptdev->gpu->pending_reqs &= ~GPU_IRQ_RESET_COMPLETED;
@@ -341,7 +349,7 @@ void panthor_gpu_suspend(struct panthor_device *ptdev)
 	if (!ptdev->reset.fast)
 		panthor_gpu_soft_reset(ptdev);
 	else
-		panthor_gpu_power_off(ptdev, L2, 1, 20000);
+		ptdev->hw->ops.l2_power_off(ptdev);
 
 	panthor_gpu_irq_suspend(&ptdev->gpu->irq);
 }
@@ -356,7 +364,7 @@ void panthor_gpu_suspend(struct panthor_device *ptdev)
 void panthor_gpu_resume(struct panthor_device *ptdev)
 {
 	panthor_gpu_irq_resume(&ptdev->gpu->irq, GPU_INTERRUPTS_MASK);
-	panthor_gpu_l2_power_on(ptdev);
+	ptdev->hw->ops.l2_power_on(ptdev);
 }
 
 /**
@@ -367,7 +375,7 @@ void panthor_gpu_resume(struct panthor_device *ptdev)
  */
 u64 panthor_gpu_read_timestamp(struct panthor_device *ptdev)
 {
-	return gpu_read64_sync(ptdev, GPU_TIMESTAMP_LO);
+	return gpu_read64_sync(ptdev, GPU_BASE(ptdev) + GPU_TIMESTAMP_LO);
 }
 
 /**
@@ -378,5 +386,5 @@ u64 panthor_gpu_read_timestamp(struct panthor_device *ptdev)
  */
 u64 panthor_gpu_read_timestamp_offset(struct panthor_device *ptdev)
 {
-	return gpu_read64(ptdev, GPU_TIMESTAMP_OFFSET_LO);
+	return gpu_read64(ptdev, GPU_BASE(ptdev) + GPU_TIMESTAMP_OFFSET_LO);
 }
diff --git a/drivers/gpu/drm/panthor/panthor_gpu.h b/drivers/gpu/drm/panthor/panthor_gpu.h
index 7f6133a66127..887075a7b4d6 100644
--- a/drivers/gpu/drm/panthor/panthor_gpu.h
+++ b/drivers/gpu/drm/panthor/panthor_gpu.h
@@ -46,6 +46,7 @@ int panthor_gpu_block_power_off(struct panthor_device *ptdev,
 				   type ## _PWRTRANS_LO, \
 				   mask, timeout_us)
 
+int panthor_gpu_l2_power_off(struct panthor_device *ptdev);
 int panthor_gpu_l2_power_on(struct panthor_device *ptdev);
 int panthor_gpu_flush_caches(struct panthor_device *ptdev,
 			     u32 l2, u32 lsc, u32 other);
diff --git a/drivers/gpu/drm/panthor/panthor_hw.c b/drivers/gpu/drm/panthor/panthor_hw.c
new file mode 100644
index 000000000000..0fb3adc093bc
--- /dev/null
+++ b/drivers/gpu/drm/panthor/panthor_hw.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0 or MIT
+/* Copyright 2024 ARM Limited. All rights reserved. */
+
+#include <linux/types.h>
+
+#include <drm/drm_managed.h>
+
+#include "panthor_device.h"
+#include "panthor_gpu.h"
+#include "panthor_hw.h"
+#include "panthor_props.h"
+#include "panthor_regs.h"
+
+enum {
+	PANTHOR_ARCH_10_8 = 0,
+	PANTHOR_ARCH_COUNT
+};
+
+static struct panthor_hw panthor_hw_devices[] = {
+	[PANTHOR_ARCH_10_8] = {
+		.arch_id = GPU_ARCH_ID_MAKE(10, 8, 0),
+		.arch_mask = GPU_ARCH_ID_MAKE(0xFF, 0, 0),
+		.map = {
+			.mmu_as_base = ARCH_10_8_MMU_AS_BASE,
+			.mmu_as_stride = ARCH_10_8_MMU_AS_STRIDE,
+			.mcu_control_base = ARCH_10_8_MCU_CONTROL_BASE,
+			.gpu_control_base = ARCH_10_8_GPU_CONTROL_BASE,
+			.gpu_irq = {
+				.name = "gpu",
+				.base = ARCH_10_8_GPU_CONTROL_BASE,
+			},
+			.job_irq = {
+				.name = "job",
+				.base = JOB_CONTROL_BASE,
+			},
+			.mmu_irq = {
+				.name = "mmu",
+				.base = MMU_CONTROL_BASE,
+			}
+		},
+		.ops = {
+			.soft_reset = panthor_gpu_soft_reset,
+			.l2_power_off = panthor_gpu_l2_power_off,
+			.l2_power_on = panthor_gpu_l2_power_on,
+		}
+	},
+};
+
+static int bind_hw_device(struct panthor_device *ptdev)
+{
+	struct panthor_gpu_id_props *gpu_id = &ptdev->props->gpu_id;
+	struct panthor_hw *hdev = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(panthor_hw_devices); i++) {
+		u32 mask = panthor_hw_devices[i].arch_mask;
+		u32 arch_id = panthor_hw_devices[i].arch_id;
+
+		if ((gpu_id->arch_id & mask) == (arch_id & mask)) {
+			hdev = &panthor_hw_devices[i];
+			break;
+		}
+	}
+
+	if (!hdev)
+		return -ENODEV;
+
+	ptdev->hw = hdev;
+
+	return 0;
+}
+
+int panthor_hw_init(struct panthor_device *ptdev)
+{
+	int err;
+
+	err = panthor_props_init(ptdev);
+	if (err)
+		return err;
+
+	err = bind_hw_device(ptdev);
+	if (err)
+		return err;
+
+	panthor_props_load(ptdev);
+
+	return 0;
+}
+
+bool panthor_hw_supports(struct panthor_device *ptdev,
+			 enum panthor_hw_feature feature)
+{
+	return test_bit(feature, ptdev->hw->features);
+}
diff --git a/drivers/gpu/drm/panthor/panthor_hw.h b/drivers/gpu/drm/panthor/panthor_hw.h
new file mode 100644
index 000000000000..3409083d09d0
--- /dev/null
+++ b/drivers/gpu/drm/panthor/panthor_hw.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0 or MIT */
+/* Copyright 2024 ARM Limited. All rights reserved. */
+
+#ifndef __PANTHOR_HW_H__
+#define __PANTHOR_HW_H__
+
+struct panthor_device;
+
+/**
+ * enum panthor_hw_feature - Bit position of each HW feature
+ *
+ * Used to define GPU specific features based on the GPU architecture ID.
+ * New feature flags will be added with support for newer GPU architectures.
+ */
+enum panthor_hw_feature {
+	PANTHOR_HW_FEATURES_END
+};
+
+struct panthor_hw_irq_regmap {
+	/** @name:  IRQ name in devicetree */
+	const char *name;
+
+	/** @base: Base address of IRQ register block */
+	const u64 base;
+};
+
+/**
+ * struct panthor_hw_regmap - Register offsets for specific register blocks
+ */
+struct panthor_hw_regmap {
+	/** @mmu_as_base: Base address of MMU address space 0 */
+	const u64 mmu_as_base;
+
+	/** @mmu_as_stride: Address offset between subsequent MMU address spaces */
+	const u64 mmu_as_stride;
+
+	/** @mcu_control_base: Base address of MCU_CONTROL */
+	const u64 mcu_control_base;
+
+	/** @gpu_control_base: Base address of GPU_CONTROL */
+	const u64 gpu_control_base;
+
+	/** @gpu_irq: GPU IRQ regmap */
+	const struct panthor_hw_irq_regmap gpu_irq;
+
+	/** @job_irq: JOB IRQ regmap */
+	const struct panthor_hw_irq_regmap job_irq;
+
+	/** @mmu_irq: MMU IRQ regmap */
+	const struct panthor_hw_irq_regmap mmu_irq;
+};
+
+/**
+ * struct panthor_hw_ops - HW operations that are specific to a GPU
+ */
+struct panthor_hw_ops {
+	/** @soft_reset: Soft reset function pointer */
+	int (*soft_reset)(struct panthor_device *ptdev);
+
+	/** @l2_power_off: L2 power off function pointer */
+	int (*l2_power_off)(struct panthor_device *ptdev);
+
+	/** @l2_power_on: L2 power on function pointer */
+	int (*l2_power_on)(struct panthor_device *ptdev);
+};
+
+/**
+ * struct panthor_hw - GPU specific register mapping and functions
+ */
+struct panthor_hw {
+	/** @arch_id: Architecture id to match against */
+	u32 arch_id;
+
+	/** @arch_mask: Mask for architecture id comparison */
+	u32 arch_mask;
+
+	/** @features: Bitmap containing panthor_hw_feature */
+	DECLARE_BITMAP(features, PANTHOR_HW_FEATURES_END);
+
+	/** @map: Panthor regmap */
+	struct panthor_hw_regmap map;
+
+	/** @ops: Panthor HW specific operations */
+	struct panthor_hw_ops ops;
+};
+
+int panthor_hw_init(struct panthor_device *ptdev);
+
+bool panthor_hw_supports(struct panthor_device *ptdev,
+			 enum panthor_hw_feature feature);
+
+#endif /* __PANTHOR_HW_H__ */
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index 2b6d147a2f0d..8a190dd2e06c 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -30,12 +30,17 @@
 #include "panthor_device.h"
 #include "panthor_gem.h"
 #include "panthor_heap.h"
+#include "panthor_hw.h"
 #include "panthor_mmu.h"
 #include "panthor_props.h"
 #include "panthor_regs.h"
 #include "panthor_sched.h"
 
 #define MAX_AS_SLOTS			32
+#define MMU_AS(ptdev, as) \
+	(ptdev->hw->map.mmu_as_base + ((as) * ptdev->hw->map.mmu_as_stride))
+
+#define MMU_BASE(ptdev) (ptdev->hw->map.mmu_irq.base)
 
 struct panthor_vm;
 
@@ -510,9 +515,9 @@ static int wait_ready(struct panthor_device *ptdev, u32 as_nr)
 	/* Wait for the MMU status to indicate there is no active command, in
 	 * case one is pending.
 	 */
-	ret = gpu_read_relaxed_poll_timeout_atomic(ptdev, AS_STATUS(as_nr), val,
-						   !(val & AS_STATUS_AS_ACTIVE),
-						   10, 100000);
+	ret = gpu_read_relaxed_poll_timeout_atomic(
+		ptdev, MMU_AS(ptdev, as_nr) + AS_STATUS, val,
+		!(val & AS_STATUS_AS_ACTIVE), 10, 100000);
 
 	if (ret) {
 		panthor_device_schedule_reset(ptdev);
@@ -529,7 +534,7 @@ static int write_cmd(struct panthor_device *ptdev, u32 as_nr, u32 cmd)
 	/* write AS_COMMAND when MMU is ready to accept another command */
 	status = wait_ready(ptdev, as_nr);
 	if (!status)
-		gpu_write(ptdev, AS_COMMAND(as_nr), cmd);
+		gpu_write(ptdev, MMU_AS(ptdev, as_nr) + AS_COMMAND, cmd);
 
 	return status;
 }
@@ -564,7 +569,7 @@ static void lock_region(struct panthor_device *ptdev, u32 as_nr,
 	region = region_width | region_start;
 
 	/* Lock the region that needs to be updated */
-	gpu_write64(ptdev, AS_LOCKADDR_LO(as_nr), region);
+	gpu_write64(ptdev, MMU_AS(ptdev, as_nr) + AS_LOCKADDR_LO, region);
 	write_cmd(ptdev, as_nr, AS_COMMAND_LOCK);
 }
 
@@ -614,9 +619,9 @@ static int panthor_mmu_as_enable(struct panthor_device *ptdev, u32 as_nr,
 	if (ret)
 		return ret;
 
-	gpu_write64(ptdev, AS_TRANSTAB_LO(as_nr), transtab);
-	gpu_write64(ptdev, AS_MEMATTR_LO(as_nr), memattr);
-	gpu_write64(ptdev, AS_TRANSCFG_LO(as_nr), transcfg);
+	gpu_write64(ptdev, MMU_AS(ptdev, as_nr) + AS_TRANSTAB_LO, transtab);
+	gpu_write64(ptdev, MMU_AS(ptdev, as_nr) + AS_MEMATTR_LO, memattr);
+	gpu_write64(ptdev, MMU_AS(ptdev, as_nr) + AS_TRANSCFG_LO, transcfg);
 
 	return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE);
 }
@@ -629,9 +634,9 @@ static int panthor_mmu_as_disable(struct panthor_device *ptdev, u32 as_nr)
 	if (ret)
 		return ret;
 
-	gpu_write64(ptdev, AS_TRANSTAB_LO(as_nr), 0);
-	gpu_write64(ptdev, AS_MEMATTR_LO(as_nr), 0);
-	gpu_write64(ptdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
+	gpu_write64(ptdev, MMU_AS(ptdev, as_nr) + AS_TRANSTAB_LO, 0);
+	gpu_write64(ptdev, MMU_AS(ptdev, as_nr) + AS_MEMATTR_LO, 0);
+	gpu_write64(ptdev, MMU_AS(ptdev, as_nr) + AS_TRANSCFG_LO, AS_TRANSCFG_ADRMODE_UNMAPPED);
 
 	return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE);
 }
@@ -767,9 +772,10 @@ int panthor_vm_active(struct panthor_vm *vm)
 	 * before enabling the AS.
 	 */
 	if (ptdev->mmu->as.faulty_mask & panthor_mmu_as_fault_mask(ptdev, as)) {
-		gpu_write(ptdev, MMU_INT_CLEAR, panthor_mmu_as_fault_mask(ptdev, as));
+		gpu_write(ptdev, MMU_BASE(ptdev) + MMU_INT_CLEAR,
+			  panthor_mmu_as_fault_mask(ptdev, as));
 		ptdev->mmu->as.faulty_mask &= ~panthor_mmu_as_fault_mask(ptdev, as);
-		gpu_write(ptdev, MMU_INT_MASK, ~ptdev->mmu->as.faulty_mask);
+		gpu_write(ptdev, MMU_BASE(ptdev) + MMU_INT_MASK, ~ptdev->mmu->as.faulty_mask);
 	}
 
 	ret = panthor_mmu_as_enable(vm->ptdev, vm->as.id, transtab, transcfg, vm->memattr);
@@ -1664,8 +1670,8 @@ static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32 status)
 		u32 access_type;
 		u32 source_id;
 
-		fault_status = gpu_read(ptdev, AS_FAULTSTATUS(as));
-		addr = gpu_read64(ptdev, AS_FAULTADDRESS_LO(as));
+		fault_status = gpu_read(ptdev, MMU_AS(ptdev, as) + AS_FAULTSTATUS);
+		addr = gpu_read64(ptdev, MMU_AS(ptdev, as) + AS_FAULTADDRESS_LO);
 
 		/* decode the fault status */
 		exception_type = fault_status & 0xFF;
@@ -1697,7 +1703,7 @@ static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32 status)
 		 * re-enabled.
 		 */
 		ptdev->mmu->irq.mask = new_int_mask;
-		gpu_write(ptdev, MMU_INT_MASK, new_int_mask);
+		gpu_write(ptdev, MMU_BASE(ptdev) + MMU_INT_MASK, new_int_mask);
 
 		if (ptdev->mmu->as.slots[as].vm)
 			ptdev->mmu->as.slots[as].vm->unhandled_fault = true;
@@ -2707,7 +2713,8 @@ int panthor_mmu_init(struct panthor_device *ptdev)
 
 	ptdev->mmu = mmu;
 
-	irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "mmu");
+	irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev),
+				      ptdev->hw->map.mmu_irq.name);
 	if (irq <= 0)
 		return -ENODEV;
 
diff --git a/drivers/gpu/drm/panthor/panthor_regs.h b/drivers/gpu/drm/panthor/panthor_regs.h
index bad172b8af82..9f22c16e5dac 100644
--- a/drivers/gpu/drm/panthor/panthor_regs.h
+++ b/drivers/gpu/drm/panthor/panthor_regs.h
@@ -12,7 +12,6 @@
 
 #include <linux/iopoll.h>
 
-/* GX10 registers */
 #define GPU_ID						0x0
 #define   GPU_ARCH_MAJOR(x)				((x) >> 28)
 #define   GPU_ARCH_MINOR(x)				(((x) & GENMASK(27, 24)) >> 24)
@@ -42,6 +41,8 @@
 #define GPU_AS_PRESENT					0x18
 #define GPU_CSF_ID					0x1C
 
+#define ARCH_10_8_GPU_CONTROL_BASE			0x0
+
 #define GPU_INT_RAWSTAT					0x20
 #define GPU_INT_CLEAR					0x24
 #define GPU_INT_MASK					0x28
@@ -145,41 +146,46 @@
 #define   GPU_COHERENCY_ACE_LITE			1
 #define   GPU_COHERENCY_NONE				31
 
-#define MCU_CONTROL					0x700
+#define ARCH_10_8_MCU_CONTROL_BASE			0x700
+
+#define MCU_CONTROL					0x0
 #define MCU_CONTROL_ENABLE				1
 #define MCU_CONTROL_AUTO				2
 #define MCU_CONTROL_DISABLE				0
 
-#define MCU_STATUS					0x704
+#define MCU_STATUS					0x4
 #define MCU_STATUS_DISABLED				0
 #define MCU_STATUS_ENABLED				1
 #define MCU_STATUS_HALT					2
 #define MCU_STATUS_FATAL				3
 
 /* Job Control regs */
-#define JOB_INT_RAWSTAT					0x1000
-#define JOB_INT_CLEAR					0x1004
-#define JOB_INT_MASK					0x1008
-#define JOB_INT_STAT					0x100c
+#define JOB_CONTROL_BASE				0x1000
+
+#define JOB_INT_RAWSTAT					0x0
+#define JOB_INT_CLEAR					0x4
+#define JOB_INT_MASK					0x8
+#define JOB_INT_STAT					0xc
 #define   JOB_INT_GLOBAL_IF				BIT(31)
 #define   JOB_INT_CSG_IF(x)				BIT(x)
 
 /* MMU regs */
-#define MMU_INT_RAWSTAT					0x2000
-#define MMU_INT_CLEAR					0x2004
-#define MMU_INT_MASK					0x2008
-#define MMU_INT_STAT					0x200c
+#define MMU_CONTROL_BASE				0x2000
+
+#define MMU_INT_RAWSTAT					0x0
+#define MMU_INT_CLEAR					0x4
+#define MMU_INT_MASK					0x8
+#define MMU_INT_STAT					0xc
 
 /* AS_COMMAND register commands */
 
-#define MMU_BASE					0x2400
-#define MMU_AS_SHIFT					6
-#define MMU_AS(as)					(MMU_BASE + ((as) << MMU_AS_SHIFT))
+#define ARCH_10_8_MMU_AS_BASE				0x2400
+#define ARCH_10_8_MMU_AS_STRIDE				0x40
 
-#define AS_TRANSTAB_LO(as)				(MMU_AS(as) + 0x0)
-#define AS_TRANSTAB_HI(as)				(MMU_AS(as) + 0x4)
-#define AS_MEMATTR_LO(as)				(MMU_AS(as) + 0x8)
-#define AS_MEMATTR_HI(as)				(MMU_AS(as) + 0xC)
+#define AS_TRANSTAB_LO					0x0
+#define AS_TRANSTAB_HI					0x4
+#define AS_MEMATTR_LO					0x8
+#define AS_MEMATTR_HI					0xC
 #define   AS_MEMATTR_AARCH64_INNER_ALLOC_IMPL		(2 << 2)
 #define   AS_MEMATTR_AARCH64_INNER_ALLOC_EXPL(w, r)	((3 << 2) | \
 							 ((w) ? BIT(0) : 0) | \
@@ -191,9 +197,9 @@
 #define   AS_MEMATTR_AARCH64_INNER_OUTER_NC		(1 << 6)
 #define   AS_MEMATTR_AARCH64_INNER_OUTER_WB		(2 << 6)
 #define   AS_MEMATTR_AARCH64_FAULT			(3 << 6)
-#define AS_LOCKADDR_LO(as)				(MMU_AS(as) + 0x10)
-#define AS_LOCKADDR_HI(as)				(MMU_AS(as) + 0x14)
-#define AS_COMMAND(as)					(MMU_AS(as) + 0x18)
+#define AS_LOCKADDR_LO					0x10
+#define AS_LOCKADDR_HI					0x14
+#define AS_COMMAND					0x18
 #define   AS_COMMAND_NOP				0
 #define   AS_COMMAND_UPDATE				1
 #define   AS_COMMAND_LOCK				2
@@ -201,18 +207,18 @@
 #define   AS_COMMAND_FLUSH_PT				4
 #define   AS_COMMAND_FLUSH_MEM				5
 #define   AS_LOCK_REGION_MIN_SIZE			(1ULL << 15)
-#define AS_FAULTSTATUS(as)				(MMU_AS(as) + 0x1C)
+#define AS_FAULTSTATUS					0x1C
 #define  AS_FAULTSTATUS_ACCESS_TYPE_MASK		(0x3 << 8)
 #define  AS_FAULTSTATUS_ACCESS_TYPE_ATOMIC		(0x0 << 8)
 #define  AS_FAULTSTATUS_ACCESS_TYPE_EX			(0x1 << 8)
 #define  AS_FAULTSTATUS_ACCESS_TYPE_READ		(0x2 << 8)
 #define  AS_FAULTSTATUS_ACCESS_TYPE_WRITE		(0x3 << 8)
-#define AS_FAULTADDRESS_LO(as)				(MMU_AS(as) + 0x20)
-#define AS_FAULTADDRESS_HI(as)				(MMU_AS(as) + 0x24)
-#define AS_STATUS(as)					(MMU_AS(as) + 0x28)
+#define AS_FAULTADDRESS_LO				0x20
+#define AS_FAULTADDRESS_HI				0x24
+#define AS_STATUS					0x28
 #define   AS_STATUS_AS_ACTIVE				BIT(0)
-#define AS_TRANSCFG_LO(as)				(MMU_AS(as) + 0x30)
-#define AS_TRANSCFG_HI(as)				(MMU_AS(as) + 0x34)
+#define AS_TRANSCFG_LO					0x30
+#define AS_TRANSCFG_HI					0x34
 #define   AS_TRANSCFG_ADRMODE_UNMAPPED			(1 << 0)
 #define   AS_TRANSCFG_ADRMODE_IDENTITY			(2 << 0)
 #define   AS_TRANSCFG_ADRMODE_AARCH64_4K		(6 << 0)
@@ -230,8 +236,6 @@
 #define   AS_TRANSCFG_DISABLE_AF_FAULT			BIT(34)
 #define   AS_TRANSCFG_WXN				BIT(35)
 #define   AS_TRANSCFG_XREADABLE				BIT(36)
-#define AS_FAULTEXTRA_LO(as)				(MMU_AS(as) + 0x38)
-#define AS_FAULTEXTRA_HI(as)				(MMU_AS(as) + 0x3C)
 
 #define CSF_GPU_LATEST_FLUSH_ID				0x10000
 
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index 209fd9576969..0c420e8c0acb 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -3838,6 +3838,7 @@ int panthor_sched_init(struct panthor_device *ptdev)
 			ptdev->props->mmu_as_count);
 		return -EINVAL;
 	}
+	gpu_as_count = ptdev->props->mmu_as_count - 1;
 
 	sched->ptdev = ptdev;
 	sched->sb_slot_count = CS_FEATURES_SCOREBOARDS(cs_iface->control->features);
-- 
2.47.1
Re: [RFC PATCH 3/4] drm/panthor: Add gpu specific initialization framework
Posted by Steven Price 12 months ago
On 19/12/2024 17:05, Karunika Choo wrote:
> This patch adds a framework for adding GPU specific code which adds the
> following gpu-specific features:
> - register base addresses
> - feature bits
> - function pointers
> 
> The above allows the handling of changes to register and register set
> offsets, as well as logical changes to the code between GPUs.

It would be nice to know what changes are expected to be able to review
this well. Do we really need all this flexibility straight away?

> 
> Signed-off-by: Karunika Choo <karunika.choo@arm.com>
> ---
>  drivers/gpu/drm/panthor/Makefile         |  1 +
>  drivers/gpu/drm/panthor/panthor_device.c | 22 ++++--
>  drivers/gpu/drm/panthor/panthor_device.h | 28 +++++--
>  drivers/gpu/drm/panthor/panthor_fw.c     | 27 ++++---
>  drivers/gpu/drm/panthor/panthor_gpu.c    | 44 ++++++-----
>  drivers/gpu/drm/panthor/panthor_gpu.h    |  1 +
>  drivers/gpu/drm/panthor/panthor_hw.c     | 94 ++++++++++++++++++++++++
>  drivers/gpu/drm/panthor/panthor_hw.h     | 92 +++++++++++++++++++++++
>  drivers/gpu/drm/panthor/panthor_mmu.c    | 41 ++++++-----
>  drivers/gpu/drm/panthor/panthor_regs.h   | 62 ++++++++--------
>  drivers/gpu/drm/panthor/panthor_sched.c  |  1 +
>  11 files changed, 323 insertions(+), 90 deletions(-)
>  create mode 100644 drivers/gpu/drm/panthor/panthor_hw.c
>  create mode 100644 drivers/gpu/drm/panthor/panthor_hw.h
> 
> diff --git a/drivers/gpu/drm/panthor/Makefile b/drivers/gpu/drm/panthor/Makefile
> index ab297637d172..e1f06396bd1d 100644
> --- a/drivers/gpu/drm/panthor/Makefile
> +++ b/drivers/gpu/drm/panthor/Makefile
> @@ -8,6 +8,7 @@ panthor-y := \
>  	panthor_gem.o \
>  	panthor_gpu.o \
>  	panthor_heap.o \
> +	panthor_hw.o \
>  	panthor_mmu.o \
>  	panthor_props.o \
>  	panthor_sched.o
> diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
> index 0b74dc628489..fd261e525b7b 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.c
> +++ b/drivers/gpu/drm/panthor/panthor_device.c
> @@ -18,6 +18,7 @@
>  #include "panthor_device.h"
>  #include "panthor_fw.h"
>  #include "panthor_gpu.h"
> +#include "panthor_hw.h"
>  #include "panthor_mmu.h"
>  #include "panthor_props.h"
>  #include "panthor_regs.h"
> @@ -116,6 +117,11 @@ void panthor_device_unplug(struct panthor_device *ptdev)
>  	complete_all(&ptdev->unplug.done);
>  }
>  
> +static bool panthor_device_is_initialized(struct panthor_device *ptdev)
> +{
> +	return !!ptdev->scheduler;
> +}
> +
>  static void panthor_device_reset_cleanup(struct drm_device *ddev, void *data)
>  {
>  	struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base);
> @@ -141,11 +147,14 @@ static void panthor_device_reset_work(struct work_struct *work)
>  	if (!drm_dev_enter(&ptdev->base, &cookie))
>  		return;
>  
> +	if (!panthor_device_is_initialized(ptdev))
> +		return;
> +

This seems like an unrelated change.

>  	panthor_sched_pre_reset(ptdev);
>  	panthor_fw_pre_reset(ptdev, true);
>  	panthor_mmu_pre_reset(ptdev);
> -	panthor_gpu_soft_reset(ptdev);
> -	panthor_gpu_l2_power_on(ptdev);
> +	ptdev->hw->ops.soft_reset(ptdev);
> +	ptdev->hw->ops.l2_power_on(ptdev);

Can we not keep the panthor_gpu_soft_reset()/panthor_gpu_l2_power_on()
functions as a stubs which do the indirect function calls?

>  	panthor_mmu_post_reset(ptdev);
>  	ret = panthor_fw_post_reset(ptdev);
>  	atomic_set(&ptdev->reset.pending, 0);
> @@ -158,11 +167,6 @@ static void panthor_device_reset_work(struct work_struct *work)
>  	}
>  }
>  
> -static bool panthor_device_is_initialized(struct panthor_device *ptdev)
> -{
> -	return !!ptdev->scheduler;
> -}
> -
>  static void panthor_device_free_page(struct drm_device *ddev, void *data)
>  {
>  	__free_page(data);
> @@ -247,6 +251,10 @@ int panthor_device_init(struct panthor_device *ptdev)
>  			return ret;
>  	}
>  
> +	ret = panthor_hw_init(ptdev);
> +	if (ret)
> +		goto err_rpm_put;
> +
>  	ret = panthor_gpu_init(ptdev);
>  	if (ret)
>  		goto err_rpm_put;
> diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
> index 60c9a67fb4a2..a984d5f9a68a 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.h
> +++ b/drivers/gpu/drm/panthor/panthor_device.h
> @@ -24,6 +24,7 @@ struct panthor_device;
>  struct panthor_gpu;
>  struct panthor_group_pool;
>  struct panthor_heap_pool;
> +struct panthor_hw;
>  struct panthor_job;
>  struct panthor_mmu;
>  struct panthor_props;
> @@ -124,6 +125,9 @@ struct panthor_device {
>  	/** @csif_info: Command stream interface information. */
>  	struct drm_panthor_csif_info csif_info;
>  
> +	/** @hw: GPU specific data */
> +	struct panthor_hw *hw;
> +
>  	/** @gpu: GPU management data. */
>  	struct panthor_gpu *gpu;
>  
> @@ -365,13 +369,14 @@ static irqreturn_t panthor_ ## __name ## _irq_raw_handler(int irq, void *data)
>  {												\
>  	struct panthor_irq *pirq = data;							\
>  	struct panthor_device *ptdev = pirq->ptdev;						\
> +	const u64 base = ptdev->hw->map.__name ## _irq.base;					\
>  												\
>  	if (atomic_read(&pirq->suspended))							\
>  		return IRQ_NONE;								\
> -	if (!gpu_read(ptdev, __reg_prefix ## _INT_STAT))					\
> +	if (!gpu_read(ptdev, base + __reg_prefix ## _INT_STAT))					\
>  		return IRQ_NONE;								\

Why isn't gpu_read() and friends updated to take the base directly,
rather than sprinkle the code with lots of open-coded addition?

[...]
> diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c
> index 51b63d258c7a..27c2e950927b 100644
> --- a/drivers/gpu/drm/panthor/panthor_fw.c
> +++ b/drivers/gpu/drm/panthor/panthor_fw.c
> @@ -21,6 +21,7 @@
>  #include "panthor_fw.h"
>  #include "panthor_gem.h"
>  #include "panthor_gpu.h"
> +#include "panthor_hw.h"
>  #include "panthor_mmu.h"
>  #include "panthor_props.h"
>  #include "panthor_regs.h"
> @@ -34,6 +35,9 @@
>  #define IDLE_HYSTERESIS_US			800
>  #define PWROFF_HYSTERESIS_US			10000
>  
> +#define MCU_BASE(ptdev) (ptdev->hw->map.mcu_control_base)
> +#define JOB_BASE(ptdev) (ptdev->hw->map.job_irq.base)
> +
>  /**
>   * struct panthor_fw_binary_hdr - Firmware binary header.
>   */
> @@ -1030,13 +1034,13 @@ static int panthor_fw_start(struct panthor_device *ptdev)
>  
>  	ptdev->fw->booted = false;
>  	panthor_job_irq_resume(&ptdev->fw->irq, ~0);
> -	gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_AUTO);
> +	gpu_write(ptdev, MCU_BASE(ptdev) + MCU_CONTROL, MCU_CONTROL_AUTO);

Do we need abstractions here? The code gets very messy. Something like:

#define gpu_mcu_write(dev, reg, value) \
	gpu_write(dev, MCU_BASE(dev) + reg, value)

[...]
> diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
> index 209fd9576969..0c420e8c0acb 100644
> --- a/drivers/gpu/drm/panthor/panthor_sched.c
> +++ b/drivers/gpu/drm/panthor/panthor_sched.c
> @@ -3838,6 +3838,7 @@ int panthor_sched_init(struct panthor_device *ptdev)
>  			ptdev->props->mmu_as_count);
>  		return -EINVAL;
>  	}
> +	gpu_as_count = ptdev->props->mmu_as_count - 1;

Unrelated change.

Thanks,
Steve