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.c...@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


Reply via email to