* [RFC PATCH 0/4] drm/panthor: Add GPU specific initialization and feature detection
@ 2024-12-19 17:05 Karunika Choo
2024-12-19 17:05 ` [RFC PATCH 1/4] drm/panthor: Add 64-bit register accessors Karunika Choo
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Karunika Choo @ 2024-12-19 17:05 UTC (permalink / raw)
To: dri-devel
Cc: nd, Boris Brezillon, Steven Price, Liviu Dudau,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, linux-kernel
This patchset attempts to define a HW abstraction framework with the
hopes of standardizing and simplifying the bring up of subsequent Mali
GPU support.
It provides abstractions to handle GPU register and register set changes,
IRQ name changes, and functional changes of subsequent GPUs based on the
architecture ID (comprised of arch_major, arch_minor and arch_rev), in
addition to arch-based feature detection.
Patch 1/4 adds 64-bit GPU register accessors with the intention of
simplifying a number of HW operations throughout the driver.
Patch 2/4 prepares the foundation for the HW abstraction layer by
providing parsing of the GPU_ID register to compose the architecture ID.
It also reduces the recurring use of MACROS throughout the driver to
parse stored register values, instead only parsing them once on
initialization while providing a common structure to access the parsed
properties.
Patch 3/4 implements the GPU specific initialization framework.
Patch 4/4 provides an example of feature detection by performing cache
flushes via the GPU_COMMAND register in place of the AS_COMMAND register
when a feature bit ise set.
Karunika Choo (4):
drm/panthor: Add 64-bit register accessors
drm/panthor: Add parsed gpu properties
drm/panthor: Add gpu specific initialization framework
drm/panthor: Use GPU_COMMAND.FLUSH_CACHES for cache maintenance
drivers/gpu/drm/panthor/Makefile | 2 +
drivers/gpu/drm/panthor/panthor_device.c | 23 +-
drivers/gpu/drm/panthor/panthor_device.h | 32 ++-
drivers/gpu/drm/panthor/panthor_fw.c | 31 ++-
drivers/gpu/drm/panthor/panthor_gpu.c | 274 +++++------------------
drivers/gpu/drm/panthor/panthor_gpu.h | 1 +
drivers/gpu/drm/panthor/panthor_heap.c | 6 +-
drivers/gpu/drm/panthor/panthor_hw.c | 97 ++++++++
drivers/gpu/drm/panthor/panthor_hw.h | 96 ++++++++
drivers/gpu/drm/panthor/panthor_mmu.c | 118 ++++++----
drivers/gpu/drm/panthor/panthor_props.c | 151 +++++++++++++
drivers/gpu/drm/panthor/panthor_props.h | 70 ++++++
drivers/gpu/drm/panthor/panthor_regs.h | 114 +++++++---
drivers/gpu/drm/panthor/panthor_sched.c | 7 +-
14 files changed, 702 insertions(+), 320 deletions(-)
create mode 100644 drivers/gpu/drm/panthor/panthor_hw.c
create mode 100644 drivers/gpu/drm/panthor/panthor_hw.h
create mode 100644 drivers/gpu/drm/panthor/panthor_props.c
create mode 100644 drivers/gpu/drm/panthor/panthor_props.h
--
2.47.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH 1/4] drm/panthor: Add 64-bit register accessors
2024-12-19 17:05 [RFC PATCH 0/4] drm/panthor: Add GPU specific initialization and feature detection Karunika Choo
@ 2024-12-19 17:05 ` Karunika Choo
2024-12-23 17:06 ` Steven Price
2024-12-19 17:05 ` [RFC PATCH 2/4] drm/panthor: Add parsed gpu properties Karunika Choo
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Karunika Choo @ 2024-12-19 17:05 UTC (permalink / raw)
To: dri-devel
Cc: nd, Boris Brezillon, Steven Price, Liviu Dudau,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, linux-kernel
This patch adds 64-bit register accessors to simplify register access in
Panthor. It also adds 64-bit variants for read_poll_timeout and replaces
all 64-bit and poll register accesses with these new functions.
Signed-off-by: Karunika Choo <karunika.choo@arm.com>
---
drivers/gpu/drm/panthor/panthor_fw.c | 11 +-
drivers/gpu/drm/panthor/panthor_gpu.c | 143 +++++++------------------
drivers/gpu/drm/panthor/panthor_mmu.c | 34 ++----
drivers/gpu/drm/panthor/panthor_regs.h | 49 +++++++++
4 files changed, 104 insertions(+), 133 deletions(-)
diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c
index 68eb4fb4d3a8..8f1b9eff66ef 100644
--- a/drivers/gpu/drm/panthor/panthor_fw.c
+++ b/drivers/gpu/drm/panthor/panthor_fw.c
@@ -1061,8 +1061,8 @@ static void panthor_fw_stop(struct panthor_device *ptdev)
u32 status;
gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_DISABLE);
- if (readl_poll_timeout(ptdev->iomem + MCU_STATUS, status,
- status == MCU_STATUS_DISABLED, 10, 100000))
+ if (gpu_read_poll_timeout(ptdev, MCU_STATUS, status,
+ status == MCU_STATUS_DISABLED, 10, 100000))
drm_err(&ptdev->base, "Failed to stop MCU");
}
@@ -1087,9 +1087,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 (!readl_poll_timeout(ptdev->iomem + MCU_STATUS, status,
- status == MCU_STATUS_HALT, 10, 100000)) {
- ptdev->reset.fast = true;
+ if (!gpu_read_poll_timeout(ptdev, MCU_STATUS, status,
+ status == MCU_STATUS_HALT, 10,
+ 100000)) {
+ ptdev->fw->fast_reset = true;
} else {
drm_warn(&ptdev->base, "Failed to cleanly suspend MCU");
}
diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c
index 671049020afa..a7d5022d34be 100644
--- a/drivers/gpu/drm/panthor/panthor_gpu.c
+++ b/drivers/gpu/drm/panthor/panthor_gpu.c
@@ -108,14 +108,9 @@ static void panthor_gpu_init_info(struct panthor_device *ptdev)
ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT);
- ptdev->gpu_info.shader_present = gpu_read(ptdev, GPU_SHADER_PRESENT_LO);
- ptdev->gpu_info.shader_present |= (u64)gpu_read(ptdev, GPU_SHADER_PRESENT_HI) << 32;
-
- ptdev->gpu_info.tiler_present = gpu_read(ptdev, GPU_TILER_PRESENT_LO);
- ptdev->gpu_info.tiler_present |= (u64)gpu_read(ptdev, GPU_TILER_PRESENT_HI) << 32;
-
- ptdev->gpu_info.l2_present = gpu_read(ptdev, GPU_L2_PRESENT_LO);
- ptdev->gpu_info.l2_present |= (u64)gpu_read(ptdev, GPU_L2_PRESENT_HI) << 32;
+ ptdev->gpu_info.shader_present = gpu_read64(ptdev, GPU_SHADER_PRESENT_LO);
+ ptdev->gpu_info.tiler_present = gpu_read64(ptdev, GPU_TILER_PRESENT_LO);
+ ptdev->gpu_info.l2_present = gpu_read64(ptdev, GPU_L2_PRESENT_LO);
arch_major = GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id);
product_major = GPU_PROD_MAJOR(ptdev->gpu_info.gpu_id);
@@ -152,8 +147,7 @@ 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 = ((u64)gpu_read(ptdev, GPU_FAULT_ADDR_HI) << 32) |
- gpu_read(ptdev, GPU_FAULT_ADDR_LO);
+ u64 address = gpu_read64(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),
@@ -244,45 +238,28 @@ int panthor_gpu_block_power_off(struct panthor_device *ptdev,
u32 pwroff_reg, u32 pwrtrans_reg,
u64 mask, u32 timeout_us)
{
- u32 val, i;
+ u64 val;
int ret;
- for (i = 0; i < 2; i++) {
- u32 mask32 = mask >> (i * 32);
-
- if (!mask32)
- continue;
-
- ret = readl_relaxed_poll_timeout(ptdev->iomem + pwrtrans_reg + (i * 4),
- val, !(mask32 & val),
- 100, timeout_us);
- if (ret) {
- drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition",
- blk_name, mask);
- return ret;
- }
+ ret = gpu_read64_relaxed_poll_timeout(ptdev, pwrtrans_reg, val,
+ !(mask & val), 100, timeout_us);
+ if (ret) {
+ drm_err(&ptdev->base,
+ "timeout waiting on %s:%llx power transition", blk_name,
+ mask);
+ return ret;
}
- if (mask & GENMASK(31, 0))
- gpu_write(ptdev, pwroff_reg, mask);
-
- if (mask >> 32)
- gpu_write(ptdev, pwroff_reg + 4, mask >> 32);
-
- for (i = 0; i < 2; i++) {
- u32 mask32 = mask >> (i * 32);
+ if (mask)
+ gpu_write64(ptdev, pwroff_reg, mask);
- if (!mask32)
- continue;
-
- ret = readl_relaxed_poll_timeout(ptdev->iomem + pwrtrans_reg + (i * 4),
- val, !(mask32 & val),
- 100, timeout_us);
- if (ret) {
- drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition",
- blk_name, mask);
- return ret;
- }
+ ret = gpu_read64_relaxed_poll_timeout(ptdev, pwrtrans_reg, val,
+ !(mask & val), 100, timeout_us);
+ if (ret) {
+ drm_err(&ptdev->base,
+ "timeout waiting on %s:%llx power transition", blk_name,
+ mask);
+ return ret;
}
return 0;
@@ -305,45 +282,26 @@ int panthor_gpu_block_power_on(struct panthor_device *ptdev,
u32 pwron_reg, u32 pwrtrans_reg,
u32 rdy_reg, u64 mask, u32 timeout_us)
{
- u32 val, i;
+ u64 val;
int ret;
- for (i = 0; i < 2; i++) {
- u32 mask32 = mask >> (i * 32);
-
- if (!mask32)
- continue;
-
- ret = readl_relaxed_poll_timeout(ptdev->iomem + pwrtrans_reg + (i * 4),
- val, !(mask32 & val),
- 100, timeout_us);
- if (ret) {
- drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition",
- blk_name, mask);
- return ret;
- }
+ ret = gpu_read64_relaxed_poll_timeout(ptdev, pwrtrans_reg, val,
+ !(mask & val), 100, timeout_us);
+ if (ret) {
+ drm_err(&ptdev->base, "timeout waiting on %s:%llx power transition",
+ blk_name, mask);
+ return ret;
}
- if (mask & GENMASK(31, 0))
- gpu_write(ptdev, pwron_reg, mask);
-
- if (mask >> 32)
- gpu_write(ptdev, pwron_reg + 4, mask >> 32);
-
- for (i = 0; i < 2; i++) {
- u32 mask32 = mask >> (i * 32);
+ if (mask)
+ gpu_write64(ptdev, pwron_reg, mask);
- if (!mask32)
- continue;
-
- ret = readl_relaxed_poll_timeout(ptdev->iomem + rdy_reg + (i * 4),
- val, (mask32 & val) == mask32,
- 100, timeout_us);
- if (ret) {
- drm_err(&ptdev->base, "timeout waiting on %s:%llx readiness",
- blk_name, mask);
- return ret;
- }
+ ret = gpu_read64_relaxed_poll_timeout(
+ ptdev, rdy_reg, val, (mask & val) == mask, 100, timeout_us);
+ if (ret) {
+ drm_err(&ptdev->base, "timeout waiting on %s:%llx readiness",
+ blk_name, mask);
+ return ret;
}
return 0;
@@ -492,26 +450,6 @@ void panthor_gpu_resume(struct panthor_device *ptdev)
panthor_gpu_l2_power_on(ptdev);
}
-/**
- * panthor_gpu_read_64bit_counter() - Read a 64-bit counter at a given offset.
- * @ptdev: Device.
- * @reg: The offset of the register to read.
- *
- * Return: The counter value.
- */
-static u64
-panthor_gpu_read_64bit_counter(struct panthor_device *ptdev, u32 reg)
-{
- u32 hi, lo;
-
- do {
- hi = gpu_read(ptdev, reg + 0x4);
- lo = gpu_read(ptdev, reg);
- } while (hi != gpu_read(ptdev, reg + 0x4));
-
- return ((u64)hi << 32) | lo;
-}
-
/**
* panthor_gpu_read_timestamp() - Read the timestamp register.
* @ptdev: Device.
@@ -520,7 +458,7 @@ panthor_gpu_read_64bit_counter(struct panthor_device *ptdev, u32 reg)
*/
u64 panthor_gpu_read_timestamp(struct panthor_device *ptdev)
{
- return panthor_gpu_read_64bit_counter(ptdev, GPU_TIMESTAMP_LO);
+ return gpu_read64_sync(ptdev, GPU_TIMESTAMP_LO);
}
/**
@@ -531,10 +469,5 @@ u64 panthor_gpu_read_timestamp(struct panthor_device *ptdev)
*/
u64 panthor_gpu_read_timestamp_offset(struct panthor_device *ptdev)
{
- u32 hi, lo;
-
- hi = gpu_read(ptdev, GPU_TIMESTAMP_OFFSET_HI);
- lo = gpu_read(ptdev, GPU_TIMESTAMP_OFFSET_LO);
-
- return ((u64)hi << 32) | lo;
+ return gpu_read64(ptdev, GPU_TIMESTAMP_OFFSET_LO);
}
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index c39e3eb1c15d..bed13089bbd4 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -509,9 +509,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 = readl_relaxed_poll_timeout_atomic(ptdev->iomem + AS_STATUS(as_nr),
- val, !(val & AS_STATUS_AS_ACTIVE),
- 10, 100000);
+ ret = gpu_read_relaxed_poll_timeout_atomic(ptdev, AS_STATUS(as_nr), val,
+ !(val & AS_STATUS_AS_ACTIVE),
+ 10, 100000);
if (ret) {
panthor_device_schedule_reset(ptdev);
@@ -563,8 +563,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_write(ptdev, AS_LOCKADDR_LO(as_nr), lower_32_bits(region));
- gpu_write(ptdev, AS_LOCKADDR_HI(as_nr), upper_32_bits(region));
+ gpu_write64(ptdev, AS_LOCKADDR_LO(as_nr), region);
write_cmd(ptdev, as_nr, AS_COMMAND_LOCK);
}
@@ -614,14 +613,9 @@ static int panthor_mmu_as_enable(struct panthor_device *ptdev, u32 as_nr,
if (ret)
return ret;
- gpu_write(ptdev, AS_TRANSTAB_LO(as_nr), lower_32_bits(transtab));
- gpu_write(ptdev, AS_TRANSTAB_HI(as_nr), upper_32_bits(transtab));
-
- gpu_write(ptdev, AS_MEMATTR_LO(as_nr), lower_32_bits(memattr));
- gpu_write(ptdev, AS_MEMATTR_HI(as_nr), upper_32_bits(memattr));
-
- gpu_write(ptdev, AS_TRANSCFG_LO(as_nr), lower_32_bits(transcfg));
- gpu_write(ptdev, AS_TRANSCFG_HI(as_nr), upper_32_bits(transcfg));
+ 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);
return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE);
}
@@ -634,14 +628,9 @@ static int panthor_mmu_as_disable(struct panthor_device *ptdev, u32 as_nr)
if (ret)
return ret;
- gpu_write(ptdev, AS_TRANSTAB_LO(as_nr), 0);
- gpu_write(ptdev, AS_TRANSTAB_HI(as_nr), 0);
-
- gpu_write(ptdev, AS_MEMATTR_LO(as_nr), 0);
- gpu_write(ptdev, AS_MEMATTR_HI(as_nr), 0);
-
- gpu_write(ptdev, AS_TRANSCFG_LO(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
- gpu_write(ptdev, AS_TRANSCFG_HI(as_nr), 0);
+ 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);
return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE);
}
@@ -1677,8 +1666,7 @@ static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32 status)
u32 source_id;
fault_status = gpu_read(ptdev, AS_FAULTSTATUS(as));
- addr = gpu_read(ptdev, AS_FAULTADDRESS_LO(as));
- addr |= (u64)gpu_read(ptdev, AS_FAULTADDRESS_HI(as)) << 32;
+ addr = gpu_read64(ptdev, AS_FAULTADDRESS_LO(as));
/* decode the fault status */
exception_type = fault_status & 0xFF;
diff --git a/drivers/gpu/drm/panthor/panthor_regs.h b/drivers/gpu/drm/panthor/panthor_regs.h
index b7b3b3add166..269c2c68dde2 100644
--- a/drivers/gpu/drm/panthor/panthor_regs.h
+++ b/drivers/gpu/drm/panthor/panthor_regs.h
@@ -10,6 +10,9 @@
#ifndef __PANTHOR_REGS_H__
#define __PANTHOR_REGS_H__
+#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)
@@ -236,4 +239,50 @@
#define gpu_read(dev, reg) \
readl((dev)->iomem + (reg))
+#define gpu_read_relaxed(dev, reg) \
+ readl_relaxed((dev)->iomem + (reg))
+
+#define gpu_write64(dev, reg, data) \
+ do { \
+ u64 __val = (u64)(data); \
+ gpu_write(dev, reg, lower_32_bits(__val)); \
+ gpu_write(dev, reg + 4, upper_32_bits(__val)); \
+ } while (0)
+
+#define gpu_read64(dev, reg) \
+ (gpu_read(dev, reg) | ((u64)gpu_read(dev, reg + 4) << 32))
+
+#define gpu_read64_relaxed(dev, reg) \
+ (gpu_read_relaxed(dev, reg) | ((u64)gpu_read_relaxed(dev, reg + 4) << 32))
+
+#define gpu_read64_sync(dev, reg_lo) \
+ ({ \
+ u32 lo, hi1, hi2; \
+ const u64 reg_hi = reg_lo + 4; \
+ do { \
+ hi1 = readl((dev)->iomem + (reg_hi)); \
+ lo = readl((dev)->iomem + (reg_lo)); \
+ hi2 = readl((dev)->iomem + (reg_hi)); \
+ } while (hi1 != hi2); \
+ lo | ((u64)hi2 << 32u); \
+ })
+
+#define gpu_read_poll_timeout(dev, reg, val, cond, delay_us, timeout_us) \
+ read_poll_timeout(gpu_read, val, cond, delay_us, timeout_us, false, dev, reg)
+
+#define gpu_read_poll_timeout_atomic(dev, reg, val, cond, delay_us, timeout_us) \
+ read_poll_timeout_atomic(gpu_read, val, cond, delay_us, timeout_us, false, dev, reg)
+
+#define gpu_read64_poll_timeout(dev, reg, val, cond, delay_us, timeout_us) \
+ read_poll_timeout(gpu_read64, val, cond, delay_us, timeout_us, false, dev, reg)
+
+#define gpu_read64_poll_timeout_atomic(dev, reg, val, cond, delay_us, timeout_us) \
+ read_poll_timeout_atomic(gpu_read64, val, cond, delay_us, timeout_us, false, dev, reg)
+
+#define gpu_read_relaxed_poll_timeout_atomic(dev, reg, val, cond, delay_us, timeout_us) \
+ read_poll_timeout_atomic(gpu_read_relaxed, val, cond, delay_us, timeout_us, false, dev, reg)
+
+#define gpu_read64_relaxed_poll_timeout(dev, reg, val, cond, delay_us, timeout_us) \
+ read_poll_timeout(gpu_read64_relaxed, val, cond, delay_us, timeout_us, false, dev, reg)
+
#endif
--
2.47.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH 2/4] drm/panthor: Add parsed gpu properties
2024-12-19 17:05 [RFC PATCH 0/4] drm/panthor: Add GPU specific initialization and feature detection Karunika Choo
2024-12-19 17:05 ` [RFC PATCH 1/4] drm/panthor: Add 64-bit register accessors Karunika Choo
@ 2024-12-19 17:05 ` Karunika Choo
2024-12-23 16:55 ` Steven Price
2024-12-19 17:05 ` [RFC PATCH 3/4] drm/panthor: Add gpu specific initialization framework Karunika Choo
2024-12-19 17:05 ` [RFC PATCH 4/4] drm/panthor: Use GPU_COMMAND.FLUSH_CACHES for cache maintenance Karunika Choo
3 siblings, 1 reply; 9+ messages in thread
From: Karunika Choo @ 2024-12-19 17:05 UTC (permalink / raw)
To: dri-devel
Cc: nd, Boris Brezillon, Steven Price, Liviu Dudau,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, linux-kernel
This patch adds parsing of GPU register fields on initialization instead of
parsing the fields each time it is needed.
Signed-off-by: Karunika Choo <karunika.choo@arm.com>
---
drivers/gpu/drm/panthor/Makefile | 1 +
drivers/gpu/drm/panthor/panthor_device.c | 1 +
drivers/gpu/drm/panthor/panthor_device.h | 4 +
drivers/gpu/drm/panthor/panthor_fw.c | 5 +-
drivers/gpu/drm/panthor/panthor_gpu.c | 105 ++--------------
drivers/gpu/drm/panthor/panthor_heap.c | 6 +-
drivers/gpu/drm/panthor/panthor_mmu.c | 21 +---
drivers/gpu/drm/panthor/panthor_props.c | 151 +++++++++++++++++++++++
drivers/gpu/drm/panthor/panthor_props.h | 70 +++++++++++
drivers/gpu/drm/panthor/panthor_regs.h | 5 +
drivers/gpu/drm/panthor/panthor_sched.c | 6 +-
11 files changed, 252 insertions(+), 123 deletions(-)
create mode 100644 drivers/gpu/drm/panthor/panthor_props.c
create mode 100644 drivers/gpu/drm/panthor/panthor_props.h
diff --git a/drivers/gpu/drm/panthor/Makefile b/drivers/gpu/drm/panthor/Makefile
index 15294719b09c..ab297637d172 100644
--- a/drivers/gpu/drm/panthor/Makefile
+++ b/drivers/gpu/drm/panthor/Makefile
@@ -9,6 +9,7 @@ panthor-y := \
panthor_gpu.o \
panthor_heap.o \
panthor_mmu.o \
+ panthor_props.o \
panthor_sched.o
obj-$(CONFIG_DRM_PANTHOR) += panthor.o
diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
index 0a37cfeeb181..0b74dc628489 100644
--- a/drivers/gpu/drm/panthor/panthor_device.c
+++ b/drivers/gpu/drm/panthor/panthor_device.c
@@ -19,6 +19,7 @@
#include "panthor_fw.h"
#include "panthor_gpu.h"
#include "panthor_mmu.h"
+#include "panthor_props.h"
#include "panthor_regs.h"
#include "panthor_sched.h"
diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
index da6574021664..60c9a67fb4a2 100644
--- a/drivers/gpu/drm/panthor/panthor_device.h
+++ b/drivers/gpu/drm/panthor/panthor_device.h
@@ -26,6 +26,7 @@ struct panthor_group_pool;
struct panthor_heap_pool;
struct panthor_job;
struct panthor_mmu;
+struct panthor_props;
struct panthor_fw;
struct panthor_perfcnt;
struct panthor_vm;
@@ -117,6 +118,9 @@ struct panthor_device {
/** @gpu_info: GPU information. */
struct drm_panthor_gpu_info gpu_info;
+ /** @props: Parsed GPU properties */
+ struct panthor_props *props;
+
/** @csif_info: Command stream interface information. */
struct drm_panthor_csif_info csif_info;
diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c
index 8f1b9eff66ef..51b63d258c7a 100644
--- a/drivers/gpu/drm/panthor/panthor_fw.c
+++ b/drivers/gpu/drm/panthor/panthor_fw.c
@@ -22,6 +22,7 @@
#include "panthor_gem.h"
#include "panthor_gpu.h"
#include "panthor_mmu.h"
+#include "panthor_props.h"
#include "panthor_regs.h"
#include "panthor_sched.h"
@@ -746,8 +747,8 @@ static int panthor_fw_load(struct panthor_device *ptdev)
int ret;
snprintf(fw_path, sizeof(fw_path), "arm/mali/arch%d.%d/%s",
- (u32)GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id),
- (u32)GPU_ARCH_MINOR(ptdev->gpu_info.gpu_id),
+ ptdev->props->gpu_id.arch_major,
+ ptdev->props->gpu_id.arch_minor,
CSF_FW_NAME);
ret = request_firmware(&fw, fw_path, ptdev->base.dev);
diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c
index a7d5022d34be..ec1780fe2638 100644
--- a/drivers/gpu/drm/panthor/panthor_gpu.c
+++ b/drivers/gpu/drm/panthor/panthor_gpu.c
@@ -18,6 +18,7 @@
#include "panthor_device.h"
#include "panthor_gpu.h"
+#include "panthor_props.h"
#include "panthor_regs.h"
/**
@@ -37,40 +38,6 @@ struct panthor_gpu {
wait_queue_head_t reqs_acked;
};
-/**
- * struct panthor_model - GPU model description
- */
-struct panthor_model {
- /** @name: Model name. */
- const char *name;
-
- /** @arch_major: Major version number of architecture. */
- u8 arch_major;
-
- /** @product_major: Major version number of product. */
- u8 product_major;
-};
-
-/**
- * GPU_MODEL() - Define a GPU model. A GPU product can be uniquely identified
- * by a combination of the major architecture version and the major product
- * version.
- * @_name: Name for the GPU model.
- * @_arch_major: Architecture major.
- * @_product_major: Product major.
- */
-#define GPU_MODEL(_name, _arch_major, _product_major) \
-{\
- .name = __stringify(_name), \
- .arch_major = _arch_major, \
- .product_major = _product_major, \
-}
-
-static const struct panthor_model gpu_models[] = {
- GPU_MODEL(g610, 10, 7),
- {},
-};
-
#define GPU_INTERRUPTS_MASK \
(GPU_IRQ_FAULT | \
GPU_IRQ_PROTM_FAULT | \
@@ -83,66 +50,6 @@ static void panthor_gpu_coherency_set(struct panthor_device *ptdev)
ptdev->coherent ? GPU_COHERENCY_PROT_BIT(ACE_LITE) : GPU_COHERENCY_NONE);
}
-static void panthor_gpu_init_info(struct panthor_device *ptdev)
-{
- const struct panthor_model *model;
- u32 arch_major, product_major;
- u32 major, minor, status;
- unsigned int i;
-
- ptdev->gpu_info.gpu_id = gpu_read(ptdev, GPU_ID);
- ptdev->gpu_info.csf_id = gpu_read(ptdev, GPU_CSF_ID);
- ptdev->gpu_info.gpu_rev = gpu_read(ptdev, GPU_REVID);
- ptdev->gpu_info.core_features = gpu_read(ptdev, GPU_CORE_FEATURES);
- ptdev->gpu_info.l2_features = gpu_read(ptdev, GPU_L2_FEATURES);
- ptdev->gpu_info.tiler_features = gpu_read(ptdev, GPU_TILER_FEATURES);
- ptdev->gpu_info.mem_features = gpu_read(ptdev, GPU_MEM_FEATURES);
- ptdev->gpu_info.mmu_features = gpu_read(ptdev, GPU_MMU_FEATURES);
- ptdev->gpu_info.thread_features = gpu_read(ptdev, GPU_THREAD_FEATURES);
- ptdev->gpu_info.max_threads = gpu_read(ptdev, GPU_THREAD_MAX_THREADS);
- ptdev->gpu_info.thread_max_workgroup_size = gpu_read(ptdev, GPU_THREAD_MAX_WORKGROUP_SIZE);
- ptdev->gpu_info.thread_max_barrier_size = gpu_read(ptdev, GPU_THREAD_MAX_BARRIER_SIZE);
- ptdev->gpu_info.coherency_features = gpu_read(ptdev, GPU_COHERENCY_FEATURES);
- for (i = 0; i < 4; i++)
- ptdev->gpu_info.texture_features[i] = gpu_read(ptdev, GPU_TEXTURE_FEATURES(i));
-
- ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT);
-
- ptdev->gpu_info.shader_present = gpu_read64(ptdev, GPU_SHADER_PRESENT_LO);
- ptdev->gpu_info.tiler_present = gpu_read64(ptdev, GPU_TILER_PRESENT_LO);
- ptdev->gpu_info.l2_present = gpu_read64(ptdev, GPU_L2_PRESENT_LO);
-
- arch_major = GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id);
- product_major = GPU_PROD_MAJOR(ptdev->gpu_info.gpu_id);
- major = GPU_VER_MAJOR(ptdev->gpu_info.gpu_id);
- minor = GPU_VER_MINOR(ptdev->gpu_info.gpu_id);
- status = GPU_VER_STATUS(ptdev->gpu_info.gpu_id);
-
- for (model = gpu_models; model->name; model++) {
- if (model->arch_major == arch_major &&
- model->product_major == product_major)
- break;
- }
-
- drm_info(&ptdev->base,
- "mali-%s id 0x%x major 0x%x minor 0x%x status 0x%x",
- model->name ?: "unknown", ptdev->gpu_info.gpu_id >> 16,
- major, minor, status);
-
- drm_info(&ptdev->base,
- "Features: L2:%#x Tiler:%#x Mem:%#x MMU:%#x AS:%#x",
- ptdev->gpu_info.l2_features,
- ptdev->gpu_info.tiler_features,
- ptdev->gpu_info.mem_features,
- ptdev->gpu_info.mmu_features,
- ptdev->gpu_info.as_present);
-
- drm_info(&ptdev->base,
- "shader_present=0x%0llx l2_present=0x%0llx tiler_present=0x%0llx",
- ptdev->gpu_info.shader_present, ptdev->gpu_info.l2_present,
- ptdev->gpu_info.tiler_present);
-}
-
static void panthor_gpu_irq_handler(struct panthor_device *ptdev, u32 status)
{
if (status & GPU_IRQ_FAULT) {
@@ -193,7 +100,6 @@ void panthor_gpu_unplug(struct panthor_device *ptdev)
int panthor_gpu_init(struct panthor_device *ptdev)
{
struct panthor_gpu *gpu;
- u32 pa_bits;
int ret, irq;
gpu = drmm_kzalloc(&ptdev->base, sizeof(*gpu), GFP_KERNEL);
@@ -203,11 +109,14 @@ int panthor_gpu_init(struct panthor_device *ptdev)
spin_lock_init(&gpu->reqs_lock);
init_waitqueue_head(&gpu->reqs_acked);
ptdev->gpu = gpu;
- panthor_gpu_init_info(ptdev);
+
+ ret = panthor_props_init(ptdev);
+ if (ret)
+ return ret;
dma_set_max_seg_size(ptdev->base.dev, UINT_MAX);
- pa_bits = GPU_MMU_FEATURES_PA_BITS(ptdev->gpu_info.mmu_features);
- ret = dma_set_mask_and_coherent(ptdev->base.dev, DMA_BIT_MASK(pa_bits));
+ ret = dma_set_mask_and_coherent(ptdev->base.dev,
+ DMA_BIT_MASK(ptdev->props->mmu_pa_bits));
if (ret)
return ret;
diff --git a/drivers/gpu/drm/panthor/panthor_heap.c b/drivers/gpu/drm/panthor/panthor_heap.c
index 3796a9eb22af..995649081a66 100644
--- a/drivers/gpu/drm/panthor/panthor_heap.c
+++ b/drivers/gpu/drm/panthor/panthor_heap.c
@@ -10,6 +10,7 @@
#include "panthor_gem.h"
#include "panthor_heap.h"
#include "panthor_mmu.h"
+#include "panthor_props.h"
#include "panthor_regs.h"
/*
@@ -101,10 +102,7 @@ struct panthor_heap_pool {
static int panthor_heap_ctx_stride(struct panthor_device *ptdev)
{
- u32 l2_features = ptdev->gpu_info.l2_features;
- u32 gpu_cache_line_size = GPU_L2_FEATURES_LINE_SIZE(l2_features);
-
- return ALIGN(HEAP_CONTEXT_SIZE, gpu_cache_line_size);
+ return ALIGN(HEAP_CONTEXT_SIZE, ptdev->props->l2_line_size);
}
static int panthor_get_heap_ctx_offset(struct panthor_heap_pool *pool, int id)
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index bed13089bbd4..2b6d147a2f0d 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -31,6 +31,7 @@
#include "panthor_gem.h"
#include "panthor_heap.h"
#include "panthor_mmu.h"
+#include "panthor_props.h"
#include "panthor_regs.h"
#include "panthor_sched.h"
@@ -695,7 +696,6 @@ static void panthor_vm_release_as_locked(struct panthor_vm *vm)
int panthor_vm_active(struct panthor_vm *vm)
{
struct panthor_device *ptdev = vm->ptdev;
- u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features);
struct io_pgtable_cfg *cfg = &io_pgtable_ops_to_pgtable(vm->pgtbl_ops)->cfg;
int ret = 0, as, cookie;
u64 transtab, transcfg;
@@ -756,7 +756,7 @@ int panthor_vm_active(struct panthor_vm *vm)
transcfg = AS_TRANSCFG_PTW_MEMATTR_WB |
AS_TRANSCFG_PTW_RA |
AS_TRANSCFG_ADRMODE_AARCH64_4K |
- AS_TRANSCFG_INA_BITS(55 - va_bits);
+ AS_TRANSCFG_INA_BITS(55 - ptdev->props->mmu_va_bits);
if (ptdev->coherent)
transcfg |= AS_TRANSCFG_PTW_SH_OS;
@@ -1456,8 +1456,7 @@ panthor_vm_create_check_args(const struct panthor_device *ptdev,
const struct drm_panthor_vm_create *args,
u64 *kernel_va_start, u64 *kernel_va_range)
{
- u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features);
- u64 full_va_range = 1ull << va_bits;
+ u64 full_va_range = 1ull << ptdev->props->mmu_va_bits;
u64 user_va_range;
if (args->flags & ~PANTHOR_VM_CREATE_FLAGS)
@@ -2258,8 +2257,8 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu,
u64 kernel_va_start, u64 kernel_va_size,
u64 auto_kernel_va_start, u64 auto_kernel_va_size)
{
- u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features);
- u32 pa_bits = GPU_MMU_FEATURES_PA_BITS(ptdev->gpu_info.mmu_features);
+ u32 va_bits = ptdev->props->mmu_va_bits;
+ u32 pa_bits = ptdev->props->mmu_pa_bits;
u64 full_va_range = 1ull << va_bits;
struct drm_gem_object *dummy_gem;
struct drm_gpu_scheduler *sched;
@@ -2688,7 +2687,6 @@ static void panthor_mmu_release_wq(struct drm_device *ddev, void *res)
*/
int panthor_mmu_init(struct panthor_device *ptdev)
{
- u32 va_bits = GPU_MMU_FEATURES_VA_BITS(ptdev->gpu_info.mmu_features);
struct panthor_mmu *mmu;
int ret, irq;
@@ -2722,15 +2720,6 @@ int panthor_mmu_init(struct panthor_device *ptdev)
if (!mmu->vm.wq)
return -ENOMEM;
- /* On 32-bit kernels, the VA space is limited by the io_pgtable_ops abstraction,
- * which passes iova as an unsigned long. Patch the mmu_features to reflect this
- * limitation.
- */
- if (va_bits > BITS_PER_LONG) {
- ptdev->gpu_info.mmu_features &= ~GENMASK(7, 0);
- ptdev->gpu_info.mmu_features |= BITS_PER_LONG;
- }
-
return drmm_add_action_or_reset(&ptdev->base, panthor_mmu_release_wq, mmu->vm.wq);
}
diff --git a/drivers/gpu/drm/panthor/panthor_props.c b/drivers/gpu/drm/panthor/panthor_props.c
new file mode 100644
index 000000000000..0a379feaf12d
--- /dev/null
+++ b/drivers/gpu/drm/panthor/panthor_props.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0 or MIT
+/* Copyright 2024 ARM Limited. All rights reserved. */
+
+#include <drm/drm_managed.h>
+
+#include "panthor_device.h"
+#include "panthor_props.h"
+#include "panthor_regs.h"
+
+static void panthor_props_arch_10_8_init_info(struct panthor_device *ptdev)
+{
+ unsigned int i;
+
+ ptdev->gpu_info.csf_id = gpu_read(ptdev, GPU_CSF_ID);
+ ptdev->gpu_info.gpu_rev = gpu_read(ptdev, GPU_REVID);
+ ptdev->gpu_info.core_features = gpu_read(ptdev, GPU_CORE_FEATURES);
+ ptdev->gpu_info.l2_features = gpu_read(ptdev, GPU_L2_FEATURES);
+ ptdev->gpu_info.tiler_features = gpu_read(ptdev, GPU_TILER_FEATURES);
+ ptdev->gpu_info.mem_features = gpu_read(ptdev, GPU_MEM_FEATURES);
+ ptdev->gpu_info.mmu_features = gpu_read(ptdev, GPU_MMU_FEATURES);
+ ptdev->gpu_info.thread_features = gpu_read(ptdev, GPU_THREAD_FEATURES);
+ ptdev->gpu_info.max_threads = gpu_read(ptdev, GPU_THREAD_MAX_THREADS);
+ ptdev->gpu_info.thread_max_workgroup_size = gpu_read(ptdev, GPU_THREAD_MAX_WORKGROUP_SIZE);
+ ptdev->gpu_info.thread_max_barrier_size = gpu_read(ptdev, GPU_THREAD_MAX_BARRIER_SIZE);
+ ptdev->gpu_info.coherency_features = gpu_read(ptdev, GPU_COHERENCY_FEATURES);
+ for (i = 0; i < 4; i++)
+ ptdev->gpu_info.texture_features[i] = gpu_read(ptdev, GPU_TEXTURE_FEATURES(i));
+}
+
+static void panthor_props_arch_10_8_parse_props(struct panthor_device *ptdev)
+{
+ struct panthor_props *props = ptdev->props;
+ struct drm_panthor_gpu_info *info = &ptdev->gpu_info;
+
+ props->shader_core_count = hweight64(info->shader_present);
+ props->mmu_va_bits = GPU_MMU_FEATURES_VA_BITS(info->mmu_features);
+ props->mmu_pa_bits = GPU_MMU_FEATURES_PA_BITS(info->mmu_features);
+ props->mmu_as_count = hweight32(info->as_present);
+ props->l2_line_size = GPU_L2_FEATURES_LINE_SIZE(info->l2_features);
+
+ /* On 32-bit kernels, the VA space is limited by the io_pgtable_ops abstraction,
+ * which passes iova as an unsigned long. Patch the mmu_features to reflect this
+ * limitation.
+ */
+ if (props->mmu_va_bits > BITS_PER_LONG) {
+ props->mmu_va_bits = BITS_PER_LONG;
+ info->mmu_features &= ~GENMASK(7, 0);
+ info->mmu_features |= BITS_PER_LONG;
+ }
+}
+
+static void panthor_props_arch_10_8_get_present_regs(struct panthor_device *ptdev)
+{
+ ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT);
+ ptdev->gpu_info.shader_present = gpu_read64(ptdev, GPU_SHADER_PRESENT_LO);
+ ptdev->gpu_info.tiler_present = gpu_read64(ptdev, GPU_TILER_PRESENT_LO);
+ ptdev->gpu_info.l2_present = gpu_read64(ptdev, GPU_L2_PRESENT_LO);
+}
+
+static char *panthor_props_get_gpu_name(struct panthor_device *ptdev)
+{
+ struct panthor_gpu_id_props *gpu_id = &ptdev->props->gpu_id;
+
+ switch (gpu_id->product_id) {
+ case GPU_PRODUCT_ID_MAKE(10, 2):
+ return "Mali-G710";
+ case GPU_PRODUCT_ID_MAKE(10, 7):
+ return "Mali-G610";
+ case GPU_PRODUCT_ID_MAKE(10, 3):
+ return "Mali-G510";
+ case GPU_PRODUCT_ID_MAKE(10, 4):
+ return "Mali-G310";
+ }
+
+ return "(Unknown Mali GPU)";
+}
+
+static void panthor_props_show_info(struct panthor_device *ptdev)
+{
+ struct panthor_gpu_id_props *gpu_id = &ptdev->props->gpu_id;
+
+ drm_info(&ptdev->base, "%s id 0x%x major 0x%x minor 0x%x status 0x%x",
+ panthor_props_get_gpu_name(ptdev), gpu_id->arch_id,
+ gpu_id->version_major, gpu_id->version_minor,
+ gpu_id->version_status);
+
+ drm_info(&ptdev->base,
+ "Features: L2:%#x Tiler:%#x Mem:%#x MMU:%#x AS:%#x",
+ ptdev->gpu_info.l2_features,
+ ptdev->gpu_info.tiler_features,
+ ptdev->gpu_info.mem_features,
+ ptdev->gpu_info.mmu_features,
+ ptdev->gpu_info.as_present);
+
+ drm_info(&ptdev->base,
+ "shader_present=0x%0llx l2_present=0x%0llx tiler_present=0x%0llx",
+ ptdev->gpu_info.shader_present, ptdev->gpu_info.l2_present,
+ ptdev->gpu_info.tiler_present);
+}
+
+int panthor_props_gpu_id_init(struct panthor_device *ptdev)
+{
+ struct panthor_gpu_id_props *gpu_id = &ptdev->props->gpu_id;
+ struct drm_panthor_gpu_info *info = &ptdev->gpu_info;
+
+ info->gpu_id = gpu_read(ptdev, GPU_ID);
+ if (!info->gpu_id)
+ return -ENXIO;
+
+ gpu_id->arch_major = GPU_ARCH_MAJOR(info->gpu_id);
+ gpu_id->arch_minor = GPU_ARCH_MINOR(info->gpu_id);
+ gpu_id->arch_rev = GPU_ARCH_REV(info->gpu_id);
+ gpu_id->product_major = GPU_PROD_MAJOR(info->gpu_id);
+ gpu_id->version_major = GPU_VER_MAJOR(info->gpu_id);
+ gpu_id->version_minor = GPU_VER_MINOR(info->gpu_id);
+ gpu_id->version_status = GPU_VER_STATUS(info->gpu_id);
+
+ gpu_id->arch_id = GPU_ARCH_ID_MAKE(
+ gpu_id->arch_major, gpu_id->arch_minor, gpu_id->arch_rev);
+ gpu_id->product_id =
+ GPU_PRODUCT_ID_MAKE(gpu_id->arch_major, gpu_id->product_major);
+
+ return 0;
+}
+
+void panthor_props_load(struct panthor_device *ptdev)
+{
+ panthor_props_arch_10_8_init_info(ptdev);
+ panthor_props_arch_10_8_get_present_regs(ptdev);
+ panthor_props_arch_10_8_parse_props(ptdev);
+
+ panthor_props_show_info(ptdev);
+}
+
+int panthor_props_init(struct panthor_device *ptdev)
+{
+ struct panthor_props *props;
+ int ret;
+
+ props = drmm_kzalloc(&ptdev->base, sizeof(*props), GFP_KERNEL);
+ if (!props)
+ return -ENOMEM;
+
+ ptdev->props = props;
+
+ ret = panthor_props_gpu_id_init(ptdev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/panthor/panthor_props.h b/drivers/gpu/drm/panthor/panthor_props.h
new file mode 100644
index 000000000000..af39a7c7433f
--- /dev/null
+++ b/drivers/gpu/drm/panthor/panthor_props.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0 or MIT */
+/* Copyright 2024 ARM Limited. All rights reserved. */
+
+#ifndef __PANTHOR_PROPS_H__
+#define __PANTHOR_PROPS_H__
+
+struct panthor_device;
+
+/**
+ * struct panthor_gpu_id_props - Parsed GPU_ID properties
+ */
+struct panthor_gpu_id_props {
+ /** @arch_major: Architecture major revision */
+ u8 arch_major;
+
+ /** @arch_minor: Architecture minor revision */
+ u8 arch_minor;
+
+ /** @arch_rev: Architecture patch revision */
+ u8 arch_rev;
+
+ /** @product_major: Product identifier */
+ u8 product_major;
+
+ /** @version_major: Major release version number */
+ u8 version_major;
+
+ /** @version_minor: Minor release version number */
+ u8 version_minor;
+
+ /** @version_status: Status of the GPU release */
+ u8 version_status;
+
+ /** @arch_id: Composite ID of arch_major, arch_minor and arch_rev */
+ u32 arch_id;
+
+ /** @arch_id: Composite ID of arch_major and product_major */
+ u32 product_id;
+};
+
+/**
+ * struct panthor_props - Parsed GPU properties
+ */
+struct panthor_props {
+ /** @gpu_id: parsed GPU_ID properties */
+ struct panthor_gpu_id_props gpu_id;
+
+ /** @shader_core_count: Number of shader cores present */
+ u8 shader_core_count;
+
+ /** @mmu_va_bits: Number of bits supported in virtual addresses */
+ u8 mmu_va_bits;
+
+ /** @mmu_pa_bits: Number of bits supported in physical addresses */
+ u8 mmu_pa_bits;
+
+ /** @mmu_as_count: Number of address spaces present */
+ u8 mmu_as_count;
+
+ /** @l2_line_size: L2 cache line size */
+ u8 l2_line_size;
+};
+
+int panthor_props_gpu_id_init(struct panthor_device *ptdev);
+
+void panthor_props_load(struct panthor_device *ptdev);
+
+int panthor_props_init(struct panthor_device *ptdev);
+
+#endif /* __PANTHOR_PROPS_H__ */
diff --git a/drivers/gpu/drm/panthor/panthor_regs.h b/drivers/gpu/drm/panthor/panthor_regs.h
index 269c2c68dde2..bad172b8af82 100644
--- a/drivers/gpu/drm/panthor/panthor_regs.h
+++ b/drivers/gpu/drm/panthor/panthor_regs.h
@@ -22,6 +22,11 @@
#define GPU_VER_MINOR(x) (((x) & GENMASK(11, 4)) >> 4)
#define GPU_VER_STATUS(x) ((x) & GENMASK(3, 0))
+#define GPU_ARCH_ID_MAKE(major, minor, rev) \
+ (((major) << 16) | ((minor) << 8) | (rev))
+#define GPU_PRODUCT_ID_MAKE(arch_major, product_major) \
+ (((arch_major) << 24) | (product_major))
+
#define GPU_L2_FEATURES 0x4
#define GPU_L2_FEATURES_LINE_SIZE(x) (1 << ((x) & GENMASK(7, 0)))
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index 77b184c3fb0c..209fd9576969 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -29,6 +29,7 @@
#include "panthor_gpu.h"
#include "panthor_heap.h"
#include "panthor_mmu.h"
+#include "panthor_props.h"
#include "panthor_regs.h"
#include "panthor_sched.h"
@@ -3832,10 +3833,9 @@ int panthor_sched_init(struct panthor_device *ptdev)
num_groups = min_t(u32, MAX_CSG_PRIO + 1, num_groups);
/* We need at least one AS for the MCU and one for the GPU contexts. */
- gpu_as_count = hweight32(ptdev->gpu_info.as_present & GENMASK(31, 1));
- if (!gpu_as_count) {
+ if (ptdev->props->mmu_as_count < 2) {
drm_err(&ptdev->base, "Not enough AS (%d, expected at least 2)",
- gpu_as_count + 1);
+ ptdev->props->mmu_as_count);
return -EINVAL;
}
--
2.47.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH 3/4] drm/panthor: Add gpu specific initialization framework
2024-12-19 17:05 [RFC PATCH 0/4] drm/panthor: Add GPU specific initialization and feature detection Karunika Choo
2024-12-19 17:05 ` [RFC PATCH 1/4] drm/panthor: Add 64-bit register accessors Karunika Choo
2024-12-19 17:05 ` [RFC PATCH 2/4] drm/panthor: Add parsed gpu properties Karunika Choo
@ 2024-12-19 17:05 ` Karunika Choo
2024-12-23 17:02 ` Steven Price
2024-12-19 17:05 ` [RFC PATCH 4/4] drm/panthor: Use GPU_COMMAND.FLUSH_CACHES for cache maintenance Karunika Choo
3 siblings, 1 reply; 9+ messages in thread
From: Karunika Choo @ 2024-12-19 17:05 UTC (permalink / raw)
To: dri-devel
Cc: nd, Boris Brezillon, Steven Price, Liviu Dudau,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, linux-kernel
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
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH 4/4] drm/panthor: Use GPU_COMMAND.FLUSH_CACHES for cache maintenance
2024-12-19 17:05 [RFC PATCH 0/4] drm/panthor: Add GPU specific initialization and feature detection Karunika Choo
` (2 preceding siblings ...)
2024-12-19 17:05 ` [RFC PATCH 3/4] drm/panthor: Add gpu specific initialization framework Karunika Choo
@ 2024-12-19 17:05 ` Karunika Choo
2024-12-23 17:05 ` Steven Price
3 siblings, 1 reply; 9+ messages in thread
From: Karunika Choo @ 2024-12-19 17:05 UTC (permalink / raw)
To: dri-devel
Cc: nd, Boris Brezillon, Steven Price, Liviu Dudau,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Simona Vetter, linux-kernel
This patch adds support for performing cache maintenance operations via
the GPU_CONTROL.GPU_COMMAND register instead of using FLUSH_PT or
FLUSH_MEM commands from the AS_COMMAND register. This feature is enabled
when the HW feature bit (PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH) is
set.
Signed-off-by: Karunika Choo <karunika.choo@arm.com>
---
drivers/gpu/drm/panthor/panthor_gpu.c | 2 +-
drivers/gpu/drm/panthor/panthor_hw.c | 3 ++
drivers/gpu/drm/panthor/panthor_hw.h | 4 +++
drivers/gpu/drm/panthor/panthor_mmu.c | 46 +++++++++++++++++++++++++--
4 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c
index 9dadcea67a39..30dcb50409dd 100644
--- a/drivers/gpu/drm/panthor/panthor_gpu.c
+++ b/drivers/gpu/drm/panthor/panthor_gpu.c
@@ -276,7 +276,7 @@ int panthor_gpu_flush_caches(struct panthor_device *ptdev,
if (!wait_event_timeout(ptdev->gpu->reqs_acked,
!(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED),
- msecs_to_jiffies(100))) {
+ msecs_to_jiffies(1000))) {
spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);
if ((ptdev->gpu->pending_reqs &
GPU_IRQ_CLEAN_CACHES_COMPLETED) != 0 &&
diff --git a/drivers/gpu/drm/panthor/panthor_hw.c b/drivers/gpu/drm/panthor/panthor_hw.c
index 0fb3adc093bc..3738f7fd106e 100644
--- a/drivers/gpu/drm/panthor/panthor_hw.c
+++ b/drivers/gpu/drm/panthor/panthor_hw.c
@@ -20,6 +20,9 @@ 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),
+ .features = {
+ BIT(PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH)
+ },
.map = {
.mmu_as_base = ARCH_10_8_MMU_AS_BASE,
.mmu_as_stride = ARCH_10_8_MMU_AS_STRIDE,
diff --git a/drivers/gpu/drm/panthor/panthor_hw.h b/drivers/gpu/drm/panthor/panthor_hw.h
index 3409083d09d0..69fa8f51a8c9 100644
--- a/drivers/gpu/drm/panthor/panthor_hw.h
+++ b/drivers/gpu/drm/panthor/panthor_hw.h
@@ -13,6 +13,10 @@ struct panthor_device;
* New feature flags will be added with support for newer GPU architectures.
*/
enum panthor_hw_feature {
+ /** @PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH: Cache maintenance via GPU_CONTROL*/
+ PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH,
+
+ /** @PANTHOR_HW_FEATURES_END: Number of HW feature bits */
PANTHOR_HW_FEATURES_END
};
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index 8a190dd2e06c..91c420538e02 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -29,6 +29,7 @@
#include "panthor_device.h"
#include "panthor_gem.h"
+#include "panthor_gpu.h"
#include "panthor_heap.h"
#include "panthor_hw.h"
#include "panthor_mmu.h"
@@ -533,12 +534,19 @@ 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, MMU_AS(ptdev, as_nr) + AS_COMMAND, cmd);
+ if (status)
+ return status;
+
+ gpu_write(ptdev, MMU_AS(ptdev, as_nr) + AS_COMMAND, cmd);
return status;
}
+static int unlock_region(struct panthor_device *ptdev, u32 as_nr)
+{
+ return write_cmd(ptdev, as_nr, AS_COMMAND_UNLOCK);
+}
+
static void lock_region(struct panthor_device *ptdev, u32 as_nr,
u64 region_start, u64 size)
{
@@ -573,6 +581,36 @@ static void lock_region(struct panthor_device *ptdev, u32 as_nr,
write_cmd(ptdev, as_nr, AS_COMMAND_LOCK);
}
+static int mmu_hw_do_flush_on_gpu_ctrl(struct panthor_device *ptdev, int as_nr,
+ u32 op)
+{
+ const u32 l2_flush = CACHE_CLEAN | CACHE_INV;
+ u32 lsc_flush = 0;
+ int ret;
+
+ if (op == AS_COMMAND_FLUSH_MEM)
+ lsc_flush = CACHE_CLEAN | CACHE_INV;
+
+ ret = wait_ready(ptdev, as_nr);
+ if (ret)
+ return ret;
+
+ ret = panthor_gpu_flush_caches(ptdev, l2_flush, lsc_flush, 0);
+ if (ret)
+ return ret;
+
+ /*
+ * Explicitly unlock the region as the AS is not unlocked
+ * automatically at the end of the operation, unlike FLUSH_MEM
+ * or FLUSH_PT.
+ */
+ ret = unlock_region(ptdev, as_nr);
+ if (ret)
+ return ret;
+
+ return wait_ready(ptdev, as_nr);
+}
+
static int mmu_hw_do_operation_locked(struct panthor_device *ptdev, int as_nr,
u64 iova, u64 size, u32 op)
{
@@ -590,6 +628,10 @@ static int mmu_hw_do_operation_locked(struct panthor_device *ptdev, int as_nr,
if (op != AS_COMMAND_UNLOCK)
lock_region(ptdev, as_nr, iova, size);
+ if (panthor_hw_supports(ptdev, PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH) &&
+ (op == AS_COMMAND_FLUSH_PT || op == AS_COMMAND_FLUSH_MEM))
+ return mmu_hw_do_flush_on_gpu_ctrl(ptdev, as_nr, op);
+
/* Run the MMU operation */
write_cmd(ptdev, as_nr, op);
--
2.47.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 2/4] drm/panthor: Add parsed gpu properties
2024-12-19 17:05 ` [RFC PATCH 2/4] drm/panthor: Add parsed gpu properties Karunika Choo
@ 2024-12-23 16:55 ` Steven Price
0 siblings, 0 replies; 9+ messages in thread
From: Steven Price @ 2024-12-23 16:55 UTC (permalink / raw)
To: Karunika Choo, dri-devel
Cc: nd, Boris Brezillon, Liviu Dudau, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
linux-kernel
On 19/12/2024 17:05, Karunika Choo wrote:
> This patch adds parsing of GPU register fields on initialization instead of
> parsing the fields each time it is needed.
Why? ;)
The commit message should ideally explain the reason behind a change
rather than the change itself (that should ideally be obvious from the
patch). (See below for more).
Also from a reviewer's perspective it's hard to review patches which
both move code between files and change it. So splitting into an initial
patch which just moves code into the new panthor_props.c and a follow up
patch would make the review easier.
> Signed-off-by: Karunika Choo <karunika.choo@arm.com>
> ---
> drivers/gpu/drm/panthor/Makefile | 1 +
> drivers/gpu/drm/panthor/panthor_device.c | 1 +
> drivers/gpu/drm/panthor/panthor_device.h | 4 +
> drivers/gpu/drm/panthor/panthor_fw.c | 5 +-
> drivers/gpu/drm/panthor/panthor_gpu.c | 105 ++--------------
> drivers/gpu/drm/panthor/panthor_heap.c | 6 +-
> drivers/gpu/drm/panthor/panthor_mmu.c | 21 +---
> drivers/gpu/drm/panthor/panthor_props.c | 151 +++++++++++++++++++++++
> drivers/gpu/drm/panthor/panthor_props.h | 70 +++++++++++
> drivers/gpu/drm/panthor/panthor_regs.h | 5 +
> drivers/gpu/drm/panthor/panthor_sched.c | 6 +-
> 11 files changed, 252 insertions(+), 123 deletions(-)
> create mode 100644 drivers/gpu/drm/panthor/panthor_props.c
> create mode 100644 drivers/gpu/drm/panthor/panthor_props.h
>
[...]
> diff --git a/drivers/gpu/drm/panthor/panthor_props.c b/drivers/gpu/drm/panthor/panthor_props.c
> new file mode 100644
> index 000000000000..0a379feaf12d
> --- /dev/null
> +++ b/drivers/gpu/drm/panthor/panthor_props.c
> @@ -0,0 +1,151 @@
> +// SPDX-License-Identifier: GPL-2.0 or MIT
> +/* Copyright 2024 ARM Limited. All rights reserved. */
> +
> +#include <drm/drm_managed.h>
> +
> +#include "panthor_device.h"
> +#include "panthor_props.h"
> +#include "panthor_regs.h"
> +
> +static void panthor_props_arch_10_8_init_info(struct panthor_device *ptdev)
> +{
> + unsigned int i;
> +
> + ptdev->gpu_info.csf_id = gpu_read(ptdev, GPU_CSF_ID);
> + ptdev->gpu_info.gpu_rev = gpu_read(ptdev, GPU_REVID);
> + ptdev->gpu_info.core_features = gpu_read(ptdev, GPU_CORE_FEATURES);
> + ptdev->gpu_info.l2_features = gpu_read(ptdev, GPU_L2_FEATURES);
> + ptdev->gpu_info.tiler_features = gpu_read(ptdev, GPU_TILER_FEATURES);
> + ptdev->gpu_info.mem_features = gpu_read(ptdev, GPU_MEM_FEATURES);
> + ptdev->gpu_info.mmu_features = gpu_read(ptdev, GPU_MMU_FEATURES);
> + ptdev->gpu_info.thread_features = gpu_read(ptdev, GPU_THREAD_FEATURES);
> + ptdev->gpu_info.max_threads = gpu_read(ptdev, GPU_THREAD_MAX_THREADS);
> + ptdev->gpu_info.thread_max_workgroup_size = gpu_read(ptdev, GPU_THREAD_MAX_WORKGROUP_SIZE);
> + ptdev->gpu_info.thread_max_barrier_size = gpu_read(ptdev, GPU_THREAD_MAX_BARRIER_SIZE);
> + ptdev->gpu_info.coherency_features = gpu_read(ptdev, GPU_COHERENCY_FEATURES);
> + for (i = 0; i < 4; i++)
> + ptdev->gpu_info.texture_features[i] = gpu_read(ptdev, GPU_TEXTURE_FEATURES(i));
> +}
> +
> +static void panthor_props_arch_10_8_parse_props(struct panthor_device *ptdev)
> +{
> + struct panthor_props *props = ptdev->props;
> + struct drm_panthor_gpu_info *info = &ptdev->gpu_info;
> +
> + props->shader_core_count = hweight64(info->shader_present);
> + props->mmu_va_bits = GPU_MMU_FEATURES_VA_BITS(info->mmu_features);
> + props->mmu_pa_bits = GPU_MMU_FEATURES_PA_BITS(info->mmu_features);
> + props->mmu_as_count = hweight32(info->as_present);
> + props->l2_line_size = GPU_L2_FEATURES_LINE_SIZE(info->l2_features);
From the function name I can guess that you want to future proof against
these registers being moved around. If so that should definitely be in
the commit message.
I'm also somewhat tempted to say we should "wait-and-see" whether this
abstraction is necessary.
> +
> + /* On 32-bit kernels, the VA space is limited by the io_pgtable_ops abstraction,
> + * which passes iova as an unsigned long. Patch the mmu_features to reflect this
> + * limitation.
> + */
> + if (props->mmu_va_bits > BITS_PER_LONG) {
> + props->mmu_va_bits = BITS_PER_LONG;
> + info->mmu_features &= ~GENMASK(7, 0);
> + info->mmu_features |= BITS_PER_LONG;
> + }
> +}
> +
> +static void panthor_props_arch_10_8_get_present_regs(struct panthor_device *ptdev)
> +{
> + ptdev->gpu_info.as_present = gpu_read(ptdev, GPU_AS_PRESENT);
> + ptdev->gpu_info.shader_present = gpu_read64(ptdev, GPU_SHADER_PRESENT_LO);
> + ptdev->gpu_info.tiler_present = gpu_read64(ptdev, GPU_TILER_PRESENT_LO);
> + ptdev->gpu_info.l2_present = gpu_read64(ptdev, GPU_L2_PRESENT_LO);
> +}
> +
> +static char *panthor_props_get_gpu_name(struct panthor_device *ptdev)
> +{
> + struct panthor_gpu_id_props *gpu_id = &ptdev->props->gpu_id;
> +
> + switch (gpu_id->product_id) {
> + case GPU_PRODUCT_ID_MAKE(10, 2):
> + return "Mali-G710";
> + case GPU_PRODUCT_ID_MAKE(10, 7):
> + return "Mali-G610";
> + case GPU_PRODUCT_ID_MAKE(10, 3):
> + return "Mali-G510";
> + case GPU_PRODUCT_ID_MAKE(10, 4):
> + return "Mali-G310";
> + }
You've sneaked in a bunch of new product names - this definitely
shouldn't be in this patch.
> +
> + return "(Unknown Mali GPU)";
> +}
> +
> +static void panthor_props_show_info(struct panthor_device *ptdev)
> +{
> + struct panthor_gpu_id_props *gpu_id = &ptdev->props->gpu_id;
> +
> + drm_info(&ptdev->base, "%s id 0x%x major 0x%x minor 0x%x status 0x%x",
> + panthor_props_get_gpu_name(ptdev), gpu_id->arch_id,
> + gpu_id->version_major, gpu_id->version_minor,
> + gpu_id->version_status);
> +
> + drm_info(&ptdev->base,
> + "Features: L2:%#x Tiler:%#x Mem:%#x MMU:%#x AS:%#x",
> + ptdev->gpu_info.l2_features,
> + ptdev->gpu_info.tiler_features,
> + ptdev->gpu_info.mem_features,
> + ptdev->gpu_info.mmu_features,
> + ptdev->gpu_info.as_present);
> +
> + drm_info(&ptdev->base,
> + "shader_present=0x%0llx l2_present=0x%0llx tiler_present=0x%0llx",
> + ptdev->gpu_info.shader_present, ptdev->gpu_info.l2_present,
> + ptdev->gpu_info.tiler_present);
> +}
> +
> +int panthor_props_gpu_id_init(struct panthor_device *ptdev)
> +{
> + struct panthor_gpu_id_props *gpu_id = &ptdev->props->gpu_id;
> + struct drm_panthor_gpu_info *info = &ptdev->gpu_info;
> +
> + info->gpu_id = gpu_read(ptdev, GPU_ID);
> + if (!info->gpu_id)
> + return -ENXIO;
> +
> + gpu_id->arch_major = GPU_ARCH_MAJOR(info->gpu_id);
> + gpu_id->arch_minor = GPU_ARCH_MINOR(info->gpu_id);
> + gpu_id->arch_rev = GPU_ARCH_REV(info->gpu_id);
> + gpu_id->product_major = GPU_PROD_MAJOR(info->gpu_id);
> + gpu_id->version_major = GPU_VER_MAJOR(info->gpu_id);
> + gpu_id->version_minor = GPU_VER_MINOR(info->gpu_id);
> + gpu_id->version_status = GPU_VER_STATUS(info->gpu_id);
Why do we need to store the GPU_ID twice (once as the gpu_id register
and once again broken down)? The bit masking/extraction is really cheap.
> +
> + gpu_id->arch_id = GPU_ARCH_ID_MAKE(
> + gpu_id->arch_major, gpu_id->arch_minor, gpu_id->arch_rev);
> + gpu_id->product_id =
> + GPU_PRODUCT_ID_MAKE(gpu_id->arch_major, gpu_id->product_major);
And here we're gluing it back together... All for the benefit of a
drm_info() - clearly not a performance path.
Steve
> +
> + return 0;
> +}
> +
> +void panthor_props_load(struct panthor_device *ptdev)
> +{
> + panthor_props_arch_10_8_init_info(ptdev);
> + panthor_props_arch_10_8_get_present_regs(ptdev);
> + panthor_props_arch_10_8_parse_props(ptdev);
> +
> + panthor_props_show_info(ptdev);
> +}
> +
> +int panthor_props_init(struct panthor_device *ptdev)
> +{
> + struct panthor_props *props;
> + int ret;
> +
> + props = drmm_kzalloc(&ptdev->base, sizeof(*props), GFP_KERNEL);
> + if (!props)
> + return -ENOMEM;
> +
> + ptdev->props = props;
> +
> + ret = panthor_props_gpu_id_init(ptdev);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> diff --git a/drivers/gpu/drm/panthor/panthor_props.h b/drivers/gpu/drm/panthor/panthor_props.h
> new file mode 100644
> index 000000000000..af39a7c7433f
> --- /dev/null
> +++ b/drivers/gpu/drm/panthor/panthor_props.h
> @@ -0,0 +1,70 @@
> +/* SPDX-License-Identifier: GPL-2.0 or MIT */
> +/* Copyright 2024 ARM Limited. All rights reserved. */
> +
> +#ifndef __PANTHOR_PROPS_H__
> +#define __PANTHOR_PROPS_H__
> +
> +struct panthor_device;
> +
> +/**
> + * struct panthor_gpu_id_props - Parsed GPU_ID properties
> + */
> +struct panthor_gpu_id_props {
> + /** @arch_major: Architecture major revision */
> + u8 arch_major;
> +
> + /** @arch_minor: Architecture minor revision */
> + u8 arch_minor;
> +
> + /** @arch_rev: Architecture patch revision */
> + u8 arch_rev;
> +
> + /** @product_major: Product identifier */
> + u8 product_major;
> +
> + /** @version_major: Major release version number */
> + u8 version_major;
> +
> + /** @version_minor: Minor release version number */
> + u8 version_minor;
> +
> + /** @version_status: Status of the GPU release */
> + u8 version_status;
> +
> + /** @arch_id: Composite ID of arch_major, arch_minor and arch_rev */
> + u32 arch_id;
> +
> + /** @arch_id: Composite ID of arch_major and product_major */
> + u32 product_id;
> +};
> +
> +/**
> + * struct panthor_props - Parsed GPU properties
> + */
> +struct panthor_props {
> + /** @gpu_id: parsed GPU_ID properties */
> + struct panthor_gpu_id_props gpu_id;
> +
> + /** @shader_core_count: Number of shader cores present */
> + u8 shader_core_count;
> +
> + /** @mmu_va_bits: Number of bits supported in virtual addresses */
> + u8 mmu_va_bits;
> +
> + /** @mmu_pa_bits: Number of bits supported in physical addresses */
> + u8 mmu_pa_bits;
> +
> + /** @mmu_as_count: Number of address spaces present */
> + u8 mmu_as_count;
> +
> + /** @l2_line_size: L2 cache line size */
> + u8 l2_line_size;
> +};
> +
> +int panthor_props_gpu_id_init(struct panthor_device *ptdev);
> +
> +void panthor_props_load(struct panthor_device *ptdev);
> +
> +int panthor_props_init(struct panthor_device *ptdev);
> +
> +#endif /* __PANTHOR_PROPS_H__ */
> diff --git a/drivers/gpu/drm/panthor/panthor_regs.h b/drivers/gpu/drm/panthor/panthor_regs.h
> index 269c2c68dde2..bad172b8af82 100644
> --- a/drivers/gpu/drm/panthor/panthor_regs.h
> +++ b/drivers/gpu/drm/panthor/panthor_regs.h
> @@ -22,6 +22,11 @@
> #define GPU_VER_MINOR(x) (((x) & GENMASK(11, 4)) >> 4)
> #define GPU_VER_STATUS(x) ((x) & GENMASK(3, 0))
>
> +#define GPU_ARCH_ID_MAKE(major, minor, rev) \
> + (((major) << 16) | ((minor) << 8) | (rev))
> +#define GPU_PRODUCT_ID_MAKE(arch_major, product_major) \
> + (((arch_major) << 24) | (product_major))
> +
> #define GPU_L2_FEATURES 0x4
> #define GPU_L2_FEATURES_LINE_SIZE(x) (1 << ((x) & GENMASK(7, 0)))
>
> diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
> index 77b184c3fb0c..209fd9576969 100644
> --- a/drivers/gpu/drm/panthor/panthor_sched.c
> +++ b/drivers/gpu/drm/panthor/panthor_sched.c
> @@ -29,6 +29,7 @@
> #include "panthor_gpu.h"
> #include "panthor_heap.h"
> #include "panthor_mmu.h"
> +#include "panthor_props.h"
> #include "panthor_regs.h"
> #include "panthor_sched.h"
>
> @@ -3832,10 +3833,9 @@ int panthor_sched_init(struct panthor_device *ptdev)
> num_groups = min_t(u32, MAX_CSG_PRIO + 1, num_groups);
>
> /* We need at least one AS for the MCU and one for the GPU contexts. */
> - gpu_as_count = hweight32(ptdev->gpu_info.as_present & GENMASK(31, 1));
> - if (!gpu_as_count) {
> + if (ptdev->props->mmu_as_count < 2) {
> drm_err(&ptdev->base, "Not enough AS (%d, expected at least 2)",
> - gpu_as_count + 1);
> + ptdev->props->mmu_as_count);
> return -EINVAL;
> }
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 3/4] drm/panthor: Add gpu specific initialization framework
2024-12-19 17:05 ` [RFC PATCH 3/4] drm/panthor: Add gpu specific initialization framework Karunika Choo
@ 2024-12-23 17:02 ` Steven Price
0 siblings, 0 replies; 9+ messages in thread
From: Steven Price @ 2024-12-23 17:02 UTC (permalink / raw)
To: Karunika Choo, dri-devel
Cc: nd, Boris Brezillon, Liviu Dudau, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
linux-kernel
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
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 4/4] drm/panthor: Use GPU_COMMAND.FLUSH_CACHES for cache maintenance
2024-12-19 17:05 ` [RFC PATCH 4/4] drm/panthor: Use GPU_COMMAND.FLUSH_CACHES for cache maintenance Karunika Choo
@ 2024-12-23 17:05 ` Steven Price
0 siblings, 0 replies; 9+ messages in thread
From: Steven Price @ 2024-12-23 17:05 UTC (permalink / raw)
To: Karunika Choo, dri-devel
Cc: nd, Boris Brezillon, Liviu Dudau, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
linux-kernel
On 19/12/2024 17:05, Karunika Choo wrote:
> This patch adds support for performing cache maintenance operations via
> the GPU_CONTROL.GPU_COMMAND register instead of using FLUSH_PT or
> FLUSH_MEM commands from the AS_COMMAND register. This feature is enabled
> when the HW feature bit (PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH) is
> set.
>
> Signed-off-by: Karunika Choo <karunika.choo@arm.com>
> ---
> drivers/gpu/drm/panthor/panthor_gpu.c | 2 +-
> drivers/gpu/drm/panthor/panthor_hw.c | 3 ++
> drivers/gpu/drm/panthor/panthor_hw.h | 4 +++
> drivers/gpu/drm/panthor/panthor_mmu.c | 46 +++++++++++++++++++++++++--
> 4 files changed, 52 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c
> index 9dadcea67a39..30dcb50409dd 100644
> --- a/drivers/gpu/drm/panthor/panthor_gpu.c
> +++ b/drivers/gpu/drm/panthor/panthor_gpu.c
> @@ -276,7 +276,7 @@ int panthor_gpu_flush_caches(struct panthor_device *ptdev,
>
> if (!wait_event_timeout(ptdev->gpu->reqs_acked,
> !(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED),
> - msecs_to_jiffies(100))) {
> + msecs_to_jiffies(1000))) {
Unrelated change (or at least not mentioned in the commit message).
> spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);
> if ((ptdev->gpu->pending_reqs &
> GPU_IRQ_CLEAN_CACHES_COMPLETED) != 0 &&
> diff --git a/drivers/gpu/drm/panthor/panthor_hw.c b/drivers/gpu/drm/panthor/panthor_hw.c
> index 0fb3adc093bc..3738f7fd106e 100644
> --- a/drivers/gpu/drm/panthor/panthor_hw.c
> +++ b/drivers/gpu/drm/panthor/panthor_hw.c
> @@ -20,6 +20,9 @@ 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),
> + .features = {
> + BIT(PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH)
> + },
It's a little odd to have a 'feature bit' to declare something that (so
far) every GPU does. Do we need this feature bit?
> .map = {
> .mmu_as_base = ARCH_10_8_MMU_AS_BASE,
> .mmu_as_stride = ARCH_10_8_MMU_AS_STRIDE,
> diff --git a/drivers/gpu/drm/panthor/panthor_hw.h b/drivers/gpu/drm/panthor/panthor_hw.h
> index 3409083d09d0..69fa8f51a8c9 100644
> --- a/drivers/gpu/drm/panthor/panthor_hw.h
> +++ b/drivers/gpu/drm/panthor/panthor_hw.h
> @@ -13,6 +13,10 @@ struct panthor_device;
> * New feature flags will be added with support for newer GPU architectures.
> */
> enum panthor_hw_feature {
> + /** @PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH: Cache maintenance via GPU_CONTROL*/
> + PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH,
> +
> + /** @PANTHOR_HW_FEATURES_END: Number of HW feature bits */
> PANTHOR_HW_FEATURES_END
> };
>
> diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
> index 8a190dd2e06c..91c420538e02 100644
> --- a/drivers/gpu/drm/panthor/panthor_mmu.c
> +++ b/drivers/gpu/drm/panthor/panthor_mmu.c
> @@ -29,6 +29,7 @@
>
> #include "panthor_device.h"
> #include "panthor_gem.h"
> +#include "panthor_gpu.h"
> #include "panthor_heap.h"
> #include "panthor_hw.h"
> #include "panthor_mmu.h"
> @@ -533,12 +534,19 @@ 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, MMU_AS(ptdev, as_nr) + AS_COMMAND, cmd);
> + if (status)
> + return status;
> +
> + gpu_write(ptdev, MMU_AS(ptdev, as_nr) + AS_COMMAND, cmd);
Please try to put simple cleanups like this in a separate patch -
there's no functional change here.
Steve
>
> return status;
> }
>
> +static int unlock_region(struct panthor_device *ptdev, u32 as_nr)
> +{
> + return write_cmd(ptdev, as_nr, AS_COMMAND_UNLOCK);
> +}
> +
> static void lock_region(struct panthor_device *ptdev, u32 as_nr,
> u64 region_start, u64 size)
> {
> @@ -573,6 +581,36 @@ static void lock_region(struct panthor_device *ptdev, u32 as_nr,
> write_cmd(ptdev, as_nr, AS_COMMAND_LOCK);
> }
>
> +static int mmu_hw_do_flush_on_gpu_ctrl(struct panthor_device *ptdev, int as_nr,
> + u32 op)
> +{
> + const u32 l2_flush = CACHE_CLEAN | CACHE_INV;
> + u32 lsc_flush = 0;
> + int ret;
> +
> + if (op == AS_COMMAND_FLUSH_MEM)
> + lsc_flush = CACHE_CLEAN | CACHE_INV;
> +
> + ret = wait_ready(ptdev, as_nr);
> + if (ret)
> + return ret;
> +
> + ret = panthor_gpu_flush_caches(ptdev, l2_flush, lsc_flush, 0);
> + if (ret)
> + return ret;
> +
> + /*
> + * Explicitly unlock the region as the AS is not unlocked
> + * automatically at the end of the operation, unlike FLUSH_MEM
> + * or FLUSH_PT.
> + */
> + ret = unlock_region(ptdev, as_nr);
> + if (ret)
> + return ret;
> +
> + return wait_ready(ptdev, as_nr);
> +}
> +
> static int mmu_hw_do_operation_locked(struct panthor_device *ptdev, int as_nr,
> u64 iova, u64 size, u32 op)
> {
> @@ -590,6 +628,10 @@ static int mmu_hw_do_operation_locked(struct panthor_device *ptdev, int as_nr,
> if (op != AS_COMMAND_UNLOCK)
> lock_region(ptdev, as_nr, iova, size);
>
> + if (panthor_hw_supports(ptdev, PANTHOR_HW_FEATURE_GPU_CTRL_CACHE_FLUSH) &&
> + (op == AS_COMMAND_FLUSH_PT || op == AS_COMMAND_FLUSH_MEM))
> + return mmu_hw_do_flush_on_gpu_ctrl(ptdev, as_nr, op);
> +
> /* Run the MMU operation */
> write_cmd(ptdev, as_nr, op);
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 1/4] drm/panthor: Add 64-bit register accessors
2024-12-19 17:05 ` [RFC PATCH 1/4] drm/panthor: Add 64-bit register accessors Karunika Choo
@ 2024-12-23 17:06 ` Steven Price
0 siblings, 0 replies; 9+ messages in thread
From: Steven Price @ 2024-12-23 17:06 UTC (permalink / raw)
To: Karunika Choo, dri-devel
Cc: nd, Boris Brezillon, Liviu Dudau, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
linux-kernel
On 19/12/2024 17:05, Karunika Choo wrote:
> This patch adds 64-bit register accessors to simplify register access in
> Panthor. It also adds 64-bit variants for read_poll_timeout and replaces
> all 64-bit and poll register accesses with these new functions.
>
> Signed-off-by: Karunika Choo <karunika.choo@arm.com>
(Minor NIT: This might be easier to review as two patches - one which
adds the new functions and a second which switching the code over to use
them).
[...]
> diff --git a/drivers/gpu/drm/panthor/panthor_regs.h b/drivers/gpu/drm/panthor/panthor_regs.h
> index b7b3b3add166..269c2c68dde2 100644
> --- a/drivers/gpu/drm/panthor/panthor_regs.h
> +++ b/drivers/gpu/drm/panthor/panthor_regs.h
> @@ -10,6 +10,9 @@
> #ifndef __PANTHOR_REGS_H__
> #define __PANTHOR_REGS_H__
>
> +#include <linux/iopoll.h>
> +
> +/* GX10 registers */
NIT: Please don't include unrelated changes like this comment.
Other than those minor issues, this looks like a nice improvement.
Steve
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2024-12-23 17:06 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-12-19 17:05 [RFC PATCH 0/4] drm/panthor: Add GPU specific initialization and feature detection Karunika Choo
2024-12-19 17:05 ` [RFC PATCH 1/4] drm/panthor: Add 64-bit register accessors Karunika Choo
2024-12-23 17:06 ` Steven Price
2024-12-19 17:05 ` [RFC PATCH 2/4] drm/panthor: Add parsed gpu properties Karunika Choo
2024-12-23 16:55 ` Steven Price
2024-12-19 17:05 ` [RFC PATCH 3/4] drm/panthor: Add gpu specific initialization framework Karunika Choo
2024-12-23 17:02 ` Steven Price
2024-12-19 17:05 ` [RFC PATCH 4/4] drm/panthor: Use GPU_COMMAND.FLUSH_CACHES for cache maintenance Karunika Choo
2024-12-23 17:05 ` Steven Price
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®