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
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
© 2016 - 2025 Red Hat, Inc.