All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] drm/imagination: Clean up MIPS firmware interfaces
@ 2026-10-14  8:13 ` Alexandru Dadu
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu,
	Matt Coster

1. Limits access to the MIPS firmware interface, keeping its state
   within the relevant implementation.
2. Align MIPS firmware headers with the other processor headers.
3. Improved logging in error paths.
4. Simplify MIPS PTE definitions.

Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
Alessio Belle (2):
      drm/imagination: Limit access to the MIPS firmware interface
      drm/imagination: Make the MIPS firmware headers arch-independent

Matt Coster (2):
      drm/imagination: Improve some logging in error paths
      drm/imagination: Simplify MIPS PTE definitions

 drivers/gpu/drm/imagination/pvr_fw.c               |   6 +-
 drivers/gpu/drm/imagination/pvr_fw.h               |  11 +-
 drivers/gpu/drm/imagination/pvr_fw_mips.c          |  79 +++--
 drivers/gpu/drm/imagination/pvr_fw_mips.h          |  49 ---
 drivers/gpu/drm/imagination/pvr_fw_riscv.c         |   1 -
 drivers/gpu/drm/imagination/pvr_mips_internal.h    | 309 +++++++++++++++++++
 .../gpu/drm/imagination/pvr_mips_internal_check.h  |  35 +++
 drivers/gpu/drm/imagination/pvr_rogue_mips.h       | 335 ---------------------
 drivers/gpu/drm/imagination/pvr_rogue_mips_check.h |  35 ---
 drivers/gpu/drm/imagination/pvr_vm_mips.c          | 162 +++++++---
 drivers/gpu/drm/imagination/pvr_vm_mips.h          |   2 +
 11 files changed, 519 insertions(+), 505 deletions(-)
---
base-commit: 6e375de99d0c420169481fcd36064177ab55b09d
change-id: 20261014-b4-simplify-mips-pte-defs-e2be1f613d14

Best regards,
--  
Alexandru Dadu <alexandru.dadu@imgtec.com>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 0/4] drm/imagination: Clean up MIPS firmware interfaces
@ 2026-10-14  8:13 ` Alexandru Dadu
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu,
	Matt Coster

1. Limits access to the MIPS firmware interface, keeping its state
   within the relevant implementation.
2. Align MIPS firmware headers with the other processor headers.
3. Improved logging in error paths.
4. Simplify MIPS PTE definitions.

Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
Alessio Belle (2):
      drm/imagination: Limit access to the MIPS firmware interface
      drm/imagination: Make the MIPS firmware headers arch-independent

Matt Coster (2):
      drm/imagination: Improve some logging in error paths
      drm/imagination: Simplify MIPS PTE definitions

 drivers/gpu/drm/imagination/pvr_fw.c               |   6 +-
 drivers/gpu/drm/imagination/pvr_fw.h               |  11 +-
 drivers/gpu/drm/imagination/pvr_fw_mips.c          |  79 +++--
 drivers/gpu/drm/imagination/pvr_fw_mips.h          |  49 ---
 drivers/gpu/drm/imagination/pvr_fw_riscv.c         |   1 -
 drivers/gpu/drm/imagination/pvr_mips_internal.h    | 309 +++++++++++++++++++
 .../gpu/drm/imagination/pvr_mips_internal_check.h  |  35 +++
 drivers/gpu/drm/imagination/pvr_rogue_mips.h       | 335 ---------------------
 drivers/gpu/drm/imagination/pvr_rogue_mips_check.h |  35 ---
 drivers/gpu/drm/imagination/pvr_vm_mips.c          | 162 +++++++---
 drivers/gpu/drm/imagination/pvr_vm_mips.h          |   2 +
 11 files changed, 519 insertions(+), 505 deletions(-)
---
base-commit: 6e375de99d0c420169481fcd36064177ab55b09d
change-id: 20261014-b4-simplify-mips-pte-defs-e2be1f613d14

Best regards,
--  
Alexandru Dadu <alexandru.dadu@imgtec.com>


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/4] drm/imagination: Limit access to the MIPS firmware interface
  2026-10-14  8:13 ` Alexandru Dadu
@ 2026-10-14  8:13   ` Alexandru Dadu
  -1 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu

From: Alessio Belle <alessio.belle@imgtec.com>

Ensure all accesses to the MIPS firmware interface are done using the
generic firmware interface, or the MIPS-specific VM interface.
To achieve this:

- Split struct pvr_fw_mips_data from the MIPS firmware interface header,
  which is essentially an interface between the "main" MIPS firmware
  logic and the MIPS VM logic, into two structures internal to the main
  and VM MIPS firmware logic.
- To restore the interface between main and VM MIPS firmware logic, add
  function to acquire the addresses of the MIPS firmware page table.
- Remove the MIPS firmware interface header.
- Rename the MIPS firmware processor headers adding an "internal"
  suffix.
- Add guard to the MIPS firmware processor header to prevent accidental
  inclusion outside of the MIPS firmware specific logic.

Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
 drivers/gpu/drm/imagination/pvr_fw.h               |  11 +-
 drivers/gpu/drm/imagination/pvr_fw_mips.c          |  57 ++++++----
 drivers/gpu/drm/imagination/pvr_fw_mips.h          |  49 ---------
 drivers/gpu/drm/imagination/pvr_fw_riscv.c         |   1 -
 ...{pvr_rogue_mips.h => pvr_rogue_mips_internal.h} |  12 +-
 ...ips_check.h => pvr_rogue_mips_internal_check.h} |   6 +-
 drivers/gpu/drm/imagination/pvr_vm_mips.c          | 122 +++++++++++++++------
 drivers/gpu/drm/imagination/pvr_vm_mips.h          |   2 +
 8 files changed, 148 insertions(+), 112 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index 4b25291135b6..0d4507f55c84 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -310,10 +310,15 @@ struct pvr_fw_device {
 	/** @funcs: Function table for the FW processor used by this device. */
 	const struct pvr_fw_defs *defs;
 
-	/** @processor_data: Pointer to data specific to FW processor. */
+	/** @processor_data: Data specific to FW processor. */
 	union {
-		/** @mips_data: Pointer to MIPS-specific data. */
-		struct pvr_fw_mips_data *mips_data;
+		/** @mips_data: MIPS-specific data. */
+		struct {
+			/** @mips_fw_data: Pointer to MIPS-FW-specific data. */
+			struct pvr_fw_mips_data *fw_data;
+			/** @mips_vm_data: Pointer to MIPS-VM-specific data. */
+			struct pvr_vm_mips_data *vm_data;
+		} mips_data;
 	} processor_data;
 
 	/** @fw_heap_info: Firmware heap information. */
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 6914fc46db50..7e4dd23e1f3f 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -3,9 +3,10 @@
 
 #include "pvr_device.h"
 #include "pvr_fw.h"
-#include "pvr_fw_mips.h"
 #include "pvr_gem.h"
-#include "pvr_rogue_mips.h"
+#define PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#include "pvr_rogue_mips_internal.h"
+#undef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_vm_mips.h"
 
 #include <linux/err.h>
@@ -15,9 +16,31 @@
 #define ROGUE_FW_HEAP_MIPS_SHIFT 24 /* 16 MB */
 #define ROGUE_FW_HEAP_MIPS_RESERVED_SIZE SZ_1M
 
+/**
+ * struct pvr_fw_mips_data - MIPS-specific data
+ */
+struct pvr_fw_mips_data {
+	/** @boot_code_dma_addr: DMA address of MIPS boot code. */
+	dma_addr_t boot_code_dma_addr;
+
+	/** @boot_data_dma_addr: DMA address of MIPS boot data. */
+	dma_addr_t boot_data_dma_addr;
+
+	/** @exception_code_dma_addr: DMA address of MIPS exception code. */
+	dma_addr_t exception_code_dma_addr;
+};
+
 static int
 pvr_mips_init(struct pvr_device *pvr_dev)
 {
+	struct pvr_fw_mips_data *fw_data;
+
+	fw_data = devm_kzalloc(pvr_dev->base.dev, sizeof(*fw_data), GFP_KERNEL);
+	if (!fw_data)
+		return -ENOMEM;
+
+	pvr_dev->fw_dev.processor_data.mips_data.fw_data = fw_data;
+
 	pvr_fw_heap_info_init(pvr_dev, ROGUE_FW_HEAP_MIPS_SHIFT, ROGUE_FW_HEAP_MIPS_RESERVED_SIZE);
 
 	return pvr_vm_mips_init(pvr_dev);
@@ -35,7 +58,7 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 		    u32 core_code_alloc_size)
 {
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
-	struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
+	struct pvr_fw_mips_data *fw_data = fw_dev->processor_data.mips_data.fw_data;
 	const struct pvr_fw_layout_entry *boot_code_entry;
 	const struct pvr_fw_layout_entry *boot_data_entry;
 	const struct pvr_fw_layout_entry *exception_code_entry;
@@ -56,12 +79,12 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 		return -EINVAL;
 
 	WARN_ON(pvr_gem_get_dma_addr(fw_dev->mem.code_obj->gem, boot_code_entry->alloc_offset,
-				     &mips_data->boot_code_dma_addr));
+				     &fw_data->boot_code_dma_addr));
 	WARN_ON(pvr_gem_get_dma_addr(fw_dev->mem.data_obj->gem, boot_data_entry->alloc_offset,
-				     &mips_data->boot_data_dma_addr));
+				     &fw_data->boot_data_dma_addr));
 	WARN_ON(pvr_gem_get_dma_addr(fw_dev->mem.code_obj->gem,
 				     exception_code_entry->alloc_offset,
-				     &mips_data->exception_code_dma_addr));
+				     &fw_data->exception_code_dma_addr));
 
 	stack_entry = pvr_fw_find_layout_entry(pvr_dev, MIPS_STACK);
 	if (!stack_entry)
@@ -76,14 +99,10 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 
 	boot_data->reg_base = pvr_dev->regs_resource->start;
 
-	for (u32 page_nr = 0; page_nr < ARRAY_SIZE(boot_data->pt_phys_addr); page_nr++) {
-		/* Firmware expects 4k pages, but host page size might be different. */
-		u32 src_page_nr = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) >> PAGE_SHIFT;
-		u32 page_offset = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) & ~PAGE_MASK;
-
-		boot_data->pt_phys_addr[page_nr] = mips_data->pt_dma_addr[src_page_nr] +
-						   page_offset;
-	}
+	err = pvr_vm_get_pt_phys_addrs(pvr_dev, boot_data->pt_phys_addr,
+				       ARRAY_SIZE(boot_data->pt_phys_addr));
+	if (err)
+		return err;
 
 	boot_data->pt_log2_page_size = ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
 	boot_data->pt_num_pages = ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES;
@@ -96,7 +115,7 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 static int
 pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 {
-	struct pvr_fw_mips_data *mips_data = pvr_dev->fw_dev.processor_data.mips_data;
+	struct pvr_fw_mips_data *fw_data = pvr_dev->fw_dev.processor_data.mips_data.fw_data;
 	const u64 remap_settings = ROGUE_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE;
 	u32 phys_bus_width;
 
@@ -119,7 +138,7 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 		       ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG2,
-		       (mips_data->boot_code_dma_addr &
+		       (fw_data->boot_code_dma_addr &
 			~ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings);
 
 	if (PVR_HAS_QUIRK(pvr_dev, 63553)) {
@@ -132,7 +151,7 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 		pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG1,
 			       ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG1_MODE_ENABLE_EN);
 		pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG2,
-			       (mips_data->boot_code_dma_addr &
+			       (fw_data->boot_code_dma_addr &
 				~ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG2_ADDR_OUT_CLRMSK) |
 			       remap_settings);
 	}
@@ -141,14 +160,14 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 		       ROGUE_MIPSFW_DATA_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2,
-		       (mips_data->boot_data_dma_addr &
+		       (fw_data->boot_data_dma_addr &
 			~ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings);
 
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1,
 		       ROGUE_MIPSFW_CODE_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG2,
-		       (mips_data->exception_code_dma_addr &
+		       (fw_data->exception_code_dma_addr &
 			~ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings);
 
 	/* Garten IDLE bit controlled by MIPS. */
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.h b/drivers/gpu/drm/imagination/pvr_fw_mips.h
deleted file mode 100644
index a0c5c41c8aa2..000000000000
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
-/* Copyright (c) 2023 Imagination Technologies Ltd. */
-
-#ifndef PVR_FW_MIPS_H
-#define PVR_FW_MIPS_H
-
-#include "pvr_rogue_mips.h"
-
-#include <asm/page.h>
-#include <linux/math.h>
-#include <linux/types.h>
-
-/* Forward declaration from pvr_gem.h. */
-struct pvr_gem_object;
-
-#define PVR_MIPS_PT_PAGE_COUNT DIV_ROUND_UP(ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
-
-/**
- * struct pvr_fw_mips_data - MIPS-specific data
- */
-struct pvr_fw_mips_data {
-	/**
-	 * @pt_pages: Pages containing MIPS pagetable.
-	 */
-	struct page *pt_pages[PVR_MIPS_PT_PAGE_COUNT];
-
-	/** @pt: Pointer to CPU mapping of MIPS pagetable. */
-	u32 *pt;
-
-	/** @pt_dma_addr: DMA mappings of MIPS pagetable. */
-	dma_addr_t pt_dma_addr[PVR_MIPS_PT_PAGE_COUNT];
-
-	/** @boot_code_dma_addr: DMA address of MIPS boot code. */
-	dma_addr_t boot_code_dma_addr;
-
-	/** @boot_data_dma_addr: DMA address of MIPS boot data. */
-	dma_addr_t boot_data_dma_addr;
-
-	/** @exception_code_dma_addr: DMA address of MIPS exception code. */
-	dma_addr_t exception_code_dma_addr;
-
-	/** @cache_policy: Cache policy for this processor. */
-	u32 cache_policy;
-
-	/** @pfn_mask: PFN mask for MIPS pagetable. */
-	u32 pfn_mask;
-};
-
-#endif /* PVR_FW_MIPS_H */
diff --git a/drivers/gpu/drm/imagination/pvr_fw_riscv.c b/drivers/gpu/drm/imagination/pvr_fw_riscv.c
index cd84635bb88d..612feb5e0ded 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_riscv.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_riscv.c
@@ -4,7 +4,6 @@
 #include "pvr_device.h"
 #include "pvr_fw.h"
 #include "pvr_fw_info.h"
-#include "pvr_fw_mips.h"
 #include "pvr_gem.h"
 #include "pvr_rogue_cr_defs.h"
 #include "pvr_rogue_riscv.h"
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_mips.h b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
similarity index 98%
rename from drivers/gpu/drm/imagination/pvr_rogue_mips.h
rename to drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
index 41ed618fda3f..68b4db83cb4b 100644
--- a/drivers/gpu/drm/imagination/pvr_rogue_mips.h
+++ b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
@@ -1,8 +1,12 @@
 /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
 /* Copyright (c) 2023 Imagination Technologies Ltd. */
 
-#ifndef PVR_ROGUE_MIPS_H
-#define PVR_ROGUE_MIPS_H
+#ifndef PVR_ROGUE_MIPS_INTERNAL_H
+#define PVR_ROGUE_MIPS_INTERNAL_H
+
+#ifndef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#error This file may only be included if explicitly defined
+#endif
 
 #include <linux/bits.h>
 #include <linux/types.h>
@@ -330,6 +334,6 @@ struct rogue_mips_state {
 	struct rogue_mips_remap_entry remap[ROGUE_MIPSFW_NUMBER_OF_REMAP_ENTRIES];
 };
 
-#include "pvr_rogue_mips_check.h"
+#include "pvr_rogue_mips_internal_check.h"
 
-#endif /* PVR_ROGUE_MIPS_H */
+#endif /* PVR_ROGUE_MIPS_INTERNAL_H */
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_mips_check.h b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
similarity index 91%
rename from drivers/gpu/drm/imagination/pvr_rogue_mips_check.h
rename to drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
index aebf231ce90f..60bc83d7cdbc 100644
--- a/drivers/gpu/drm/imagination/pvr_rogue_mips_check.h
+++ b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
 /* Copyright (c) 2023 Imagination Technologies Ltd. */
 
-#ifndef PVR_ROGUE_MIPS_CHECK_H
-#define PVR_ROGUE_MIPS_CHECK_H
+#ifndef PVR_ROGUE_MIPS_INTERNAL_CHECK_H
+#define PVR_ROGUE_MIPS_INTERNAL_CHECK_H
 
 #include "pvr_check.h"
 
@@ -32,4 +32,4 @@ OFFSET_CHECK(struct rogue_mips_state, tlb, 44);
 OFFSET_CHECK(struct rogue_mips_state, remap, 300);
 SIZE_CHECK(struct rogue_mips_state, 684);
 
-#endif /* PVR_ROGUE_MIPS_CHECK_H */
+#endif /* PVR_ROGUE_MIPS_INTERNAL_CHECK_H */
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
index 5847a1c92bea..264ea0fccf9c 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
@@ -2,10 +2,11 @@
 /* Copyright (c) 2023 Imagination Technologies Ltd. */
 
 #include "pvr_device.h"
-#include "pvr_fw_mips.h"
 #include "pvr_gem.h"
 #include "pvr_mmu.h"
-#include "pvr_rogue_mips.h"
+#define PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#include "pvr_rogue_mips_internal.h"
+#undef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_vm.h"
 #include "pvr_vm_mips.h"
 
@@ -16,6 +17,31 @@
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 
+#define PVR_MIPS_PT_PAGE_COUNT \
+	DIV_ROUND_UP(ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
+
+/**
+ * struct pvr_vm_mips_data - MIPS-VM-specific data
+ */
+struct pvr_vm_mips_data {
+	/**
+	 * @pt_pages: Pages containing MIPS pagetable.
+	 */
+	struct page *pt_pages[PVR_MIPS_PT_PAGE_COUNT];
+
+	/** @pt: Pointer to CPU mapping of MIPS pagetable. */
+	u32 *pt;
+
+	/** @pt_dma_addr: DMA mappings of MIPS pagetable. */
+	dma_addr_t pt_dma_addr[PVR_MIPS_PT_PAGE_COUNT];
+
+	/** @cache_policy: Cache policy for this processor. */
+	u32 cache_policy;
+
+	/** @pfn_mask: PFN mask for MIPS pagetable. */
+	u32 pfn_mask;
+};
+
 /**
  * pvr_vm_mips_init() - Initialise MIPS FW pagetable
  * @pvr_dev: Target PowerVR device.
@@ -31,7 +57,7 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)
 {
 	u32 pt_size = 1 << ROGUE_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev);
 	struct device *dev = from_pvr_device(pvr_dev)->dev;
-	struct pvr_fw_mips_data *mips_data;
+	struct pvr_vm_mips_data *vm_data;
 	u32 phys_bus_width;
 	int page_nr;
 	int err;
@@ -43,49 +69,49 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)
 	if (PVR_FEATURE_VALUE(pvr_dev, phys_bus_width, &phys_bus_width))
 		return -EINVAL;
 
-	mips_data = drmm_kzalloc(from_pvr_device(pvr_dev), sizeof(*mips_data), GFP_KERNEL);
-	if (!mips_data)
+	vm_data = drmm_kzalloc(from_pvr_device(pvr_dev), sizeof(*vm_data), GFP_KERNEL);
+	if (!vm_data)
 		return -ENOMEM;
 
 	for (page_nr = 0; page_nr < PVR_MIPS_PT_PAGE_COUNT; page_nr++) {
-		mips_data->pt_pages[page_nr] = alloc_page(GFP_KERNEL | __GFP_ZERO);
-		if (!mips_data->pt_pages[page_nr]) {
+		vm_data->pt_pages[page_nr] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (!vm_data->pt_pages[page_nr]) {
 			err = -ENOMEM;
 			goto err_free_pages;
 		}
 
-		mips_data->pt_dma_addr[page_nr] = dma_map_page(dev, mips_data->pt_pages[page_nr], 0,
-							       PAGE_SIZE, DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, mips_data->pt_dma_addr[page_nr])) {
+		vm_data->pt_dma_addr[page_nr] = dma_map_page(dev, vm_data->pt_pages[page_nr], 0,
+							     PAGE_SIZE, DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, vm_data->pt_dma_addr[page_nr])) {
 			err = -ENOMEM;
-			__free_page(mips_data->pt_pages[page_nr]);
+			__free_page(vm_data->pt_pages[page_nr]);
 			goto err_free_pages;
 		}
 	}
 
-	mips_data->pt = vmap(mips_data->pt_pages, pt_size >> PAGE_SHIFT, VM_MAP,
-			     pgprot_writecombine(PAGE_KERNEL));
-	if (!mips_data->pt) {
+	vm_data->pt = vmap(vm_data->pt_pages, pt_size >> PAGE_SHIFT, VM_MAP,
+			   pgprot_writecombine(PAGE_KERNEL));
+	if (!vm_data->pt) {
 		err = -ENOMEM;
 		goto err_free_pages;
 	}
 
-	mips_data->pfn_mask = (phys_bus_width > 32) ? ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
-						      ROGUE_MIPSFW_ENTRYLO_PFN_MASK;
+	vm_data->pfn_mask = (phys_bus_width > 32) ? ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
+						    ROGUE_MIPSFW_ENTRYLO_PFN_MASK;
 
-	mips_data->cache_policy = (phys_bus_width > 32) ? ROGUE_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
-							  ROGUE_MIPSFW_CACHED_POLICY;
+	vm_data->cache_policy = (phys_bus_width > 32) ? ROGUE_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
+							ROGUE_MIPSFW_CACHED_POLICY;
 
-	pvr_dev->fw_dev.processor_data.mips_data = mips_data;
+	pvr_dev->fw_dev.processor_data.mips_data.vm_data = vm_data;
 
 	return 0;
 
 err_free_pages:
 	while (--page_nr >= 0) {
 		dma_unmap_page(from_pvr_device(pvr_dev)->dev,
-			       mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
+			       vm_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
 
-		__free_page(mips_data->pt_pages[page_nr]);
+		__free_page(vm_data->pt_pages[page_nr]);
 	}
 
 	return err;
@@ -99,17 +125,17 @@ void
 pvr_vm_mips_fini(struct pvr_device *pvr_dev)
 {
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
-	struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
+	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
 
-	vunmap(mips_data->pt);
+	vunmap(vm_data->pt);
 	for (int page_nr = PVR_MIPS_PT_PAGE_COUNT - 1; page_nr >= 0; page_nr--) {
 		dma_unmap_page(from_pvr_device(pvr_dev)->dev,
-			       mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
+			       vm_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
 
-		__free_page(mips_data->pt_pages[page_nr]);
+		__free_page(vm_data->pt_pages[page_nr]);
 	}
 
-	fw_dev->processor_data.mips_data = NULL;
+	fw_dev->processor_data.mips_data.vm_data = NULL;
 }
 
 static u32
@@ -145,7 +171,7 @@ int
 pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 {
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
-	struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
+	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
 	struct pvr_gem_object *pvr_obj = fw_obj->gem;
 	const u64 start = fw_obj->fw_mm_node.start;
 	const u64 size = fw_obj->fw_mm_node.size;
@@ -174,7 +200,7 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 	if (pvr_obj->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
 		cache_policy = ROGUE_MIPSFW_UNCACHED_CACHE_POLICY;
 	else
-		cache_policy = mips_data->cache_policy;
+		cache_policy = vm_data->cache_policy;
 
 	pte_flags = get_mips_pte_flags(true, true, cache_policy);
 
@@ -190,10 +216,10 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 			goto err_unmap_pages;
 
 		pte = ((dma_addr >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-		       << ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT) & mips_data->pfn_mask;
+		       << ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT) & vm_data->pfn_mask;
 		pte |= pte_flags;
 
-		WRITE_ONCE(mips_data->pt[pfn], pte);
+		WRITE_ONCE(vm_data->pt[pfn], pte);
 	}
 
 	pvr_mmu_flush_request_all(pvr_dev);
@@ -202,7 +228,7 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 
 err_unmap_pages:
 	while (--pfn >= start_pfn)
-		WRITE_ONCE(mips_data->pt[pfn], 0);
+		WRITE_ONCE(vm_data->pt[pfn], 0);
 
 	pvr_mmu_flush_request_all(pvr_dev);
 	WARN_ON(pvr_mmu_flush_exec(pvr_dev, true));
@@ -219,7 +245,7 @@ void
 pvr_vm_mips_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 {
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
-	struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
+	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
 	const u64 start = fw_obj->fw_mm_node.start;
 	const u64 size = fw_obj->fw_mm_node.size;
 	const u64 end = start + size;
@@ -230,8 +256,38 @@ pvr_vm_mips_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 			    ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
 
 	for (u32 pfn = start_pfn; pfn < end_pfn; pfn++)
-		WRITE_ONCE(mips_data->pt[pfn], 0);
+		WRITE_ONCE(vm_data->pt[pfn], 0);
 
 	pvr_mmu_flush_request_all(pvr_dev);
 	WARN_ON(pvr_mmu_flush_exec(pvr_dev, true));
 }
+
+/**
+ * pvr_vm_get_pt_phys_addrs() - Acquire the physical addresses of the MIPS FW page table pages
+ * @pvr_dev: Target PowerVR device.
+ * @phys_addrs: Output array for physical addresses of MIPS FW page table pages.
+ * @max_num_addrs: Maximum number of addresses that can be written to @phys_addrs.
+ *
+ * Returns:
+ *  * 0 on success, or
+ *  * -%EINVAL if @phys_addrs cannot accommodate all MIPS FW page table pages.
+ */
+int
+pvr_vm_get_pt_phys_addrs(struct pvr_device *pvr_dev, u64 *phys_addrs, int max_num_addrs)
+{
+	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
+	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
+
+	if (ARRAY_SIZE(vm_data->pt_pages) > max_num_addrs)
+		return -EINVAL;
+
+	for (u32 page_nr = 0; page_nr < max_num_addrs; page_nr++) {
+		/* Firmware expects 4k pages, but host page size might be different. */
+		u32 src_page_nr = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) >> PAGE_SHIFT;
+		u32 page_offset = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) & ~PAGE_MASK;
+
+		phys_addrs[page_nr] = vm_data->pt_dma_addr[src_page_nr] + page_offset;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.h b/drivers/gpu/drm/imagination/pvr_vm_mips.h
index 0fd59f68fb5b..3db0606c5037 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.h
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.h
@@ -18,5 +18,7 @@ int
 pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj);
 void
 pvr_vm_mips_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj);
+int
+pvr_vm_get_pt_phys_addrs(struct pvr_device *pvr_dev, u64 *phys_addrs, int max_num_addrs);
 
 #endif /* PVR_VM_MIPS_H */

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 1/4] drm/imagination: Limit access to the MIPS firmware interface
@ 2026-10-14  8:13   ` Alexandru Dadu
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu

From: Alessio Belle <alessio.belle@imgtec.com>

Ensure all accesses to the MIPS firmware interface are done using the
generic firmware interface, or the MIPS-specific VM interface.
To achieve this:

- Split struct pvr_fw_mips_data from the MIPS firmware interface header,
  which is essentially an interface between the "main" MIPS firmware
  logic and the MIPS VM logic, into two structures internal to the main
  and VM MIPS firmware logic.
- To restore the interface between main and VM MIPS firmware logic, add
  function to acquire the addresses of the MIPS firmware page table.
- Remove the MIPS firmware interface header.
- Rename the MIPS firmware processor headers adding an "internal"
  suffix.
- Add guard to the MIPS firmware processor header to prevent accidental
  inclusion outside of the MIPS firmware specific logic.

Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
 drivers/gpu/drm/imagination/pvr_fw.h               |  11 +-
 drivers/gpu/drm/imagination/pvr_fw_mips.c          |  57 ++++++----
 drivers/gpu/drm/imagination/pvr_fw_mips.h          |  49 ---------
 drivers/gpu/drm/imagination/pvr_fw_riscv.c         |   1 -
 ...{pvr_rogue_mips.h => pvr_rogue_mips_internal.h} |  12 +-
 ...ips_check.h => pvr_rogue_mips_internal_check.h} |   6 +-
 drivers/gpu/drm/imagination/pvr_vm_mips.c          | 122 +++++++++++++++------
 drivers/gpu/drm/imagination/pvr_vm_mips.h          |   2 +
 8 files changed, 148 insertions(+), 112 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw.h b/drivers/gpu/drm/imagination/pvr_fw.h
index 4b25291135b6..0d4507f55c84 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.h
+++ b/drivers/gpu/drm/imagination/pvr_fw.h
@@ -310,10 +310,15 @@ struct pvr_fw_device {
 	/** @funcs: Function table for the FW processor used by this device. */
 	const struct pvr_fw_defs *defs;
 
-	/** @processor_data: Pointer to data specific to FW processor. */
+	/** @processor_data: Data specific to FW processor. */
 	union {
-		/** @mips_data: Pointer to MIPS-specific data. */
-		struct pvr_fw_mips_data *mips_data;
+		/** @mips_data: MIPS-specific data. */
+		struct {
+			/** @mips_fw_data: Pointer to MIPS-FW-specific data. */
+			struct pvr_fw_mips_data *fw_data;
+			/** @mips_vm_data: Pointer to MIPS-VM-specific data. */
+			struct pvr_vm_mips_data *vm_data;
+		} mips_data;
 	} processor_data;
 
 	/** @fw_heap_info: Firmware heap information. */
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 6914fc46db50..7e4dd23e1f3f 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -3,9 +3,10 @@
 
 #include "pvr_device.h"
 #include "pvr_fw.h"
-#include "pvr_fw_mips.h"
 #include "pvr_gem.h"
-#include "pvr_rogue_mips.h"
+#define PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#include "pvr_rogue_mips_internal.h"
+#undef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_vm_mips.h"
 
 #include <linux/err.h>
@@ -15,9 +16,31 @@
 #define ROGUE_FW_HEAP_MIPS_SHIFT 24 /* 16 MB */
 #define ROGUE_FW_HEAP_MIPS_RESERVED_SIZE SZ_1M
 
+/**
+ * struct pvr_fw_mips_data - MIPS-specific data
+ */
+struct pvr_fw_mips_data {
+	/** @boot_code_dma_addr: DMA address of MIPS boot code. */
+	dma_addr_t boot_code_dma_addr;
+
+	/** @boot_data_dma_addr: DMA address of MIPS boot data. */
+	dma_addr_t boot_data_dma_addr;
+
+	/** @exception_code_dma_addr: DMA address of MIPS exception code. */
+	dma_addr_t exception_code_dma_addr;
+};
+
 static int
 pvr_mips_init(struct pvr_device *pvr_dev)
 {
+	struct pvr_fw_mips_data *fw_data;
+
+	fw_data = devm_kzalloc(pvr_dev->base.dev, sizeof(*fw_data), GFP_KERNEL);
+	if (!fw_data)
+		return -ENOMEM;
+
+	pvr_dev->fw_dev.processor_data.mips_data.fw_data = fw_data;
+
 	pvr_fw_heap_info_init(pvr_dev, ROGUE_FW_HEAP_MIPS_SHIFT, ROGUE_FW_HEAP_MIPS_RESERVED_SIZE);
 
 	return pvr_vm_mips_init(pvr_dev);
@@ -35,7 +58,7 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 		    u32 core_code_alloc_size)
 {
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
-	struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
+	struct pvr_fw_mips_data *fw_data = fw_dev->processor_data.mips_data.fw_data;
 	const struct pvr_fw_layout_entry *boot_code_entry;
 	const struct pvr_fw_layout_entry *boot_data_entry;
 	const struct pvr_fw_layout_entry *exception_code_entry;
@@ -56,12 +79,12 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 		return -EINVAL;
 
 	WARN_ON(pvr_gem_get_dma_addr(fw_dev->mem.code_obj->gem, boot_code_entry->alloc_offset,
-				     &mips_data->boot_code_dma_addr));
+				     &fw_data->boot_code_dma_addr));
 	WARN_ON(pvr_gem_get_dma_addr(fw_dev->mem.data_obj->gem, boot_data_entry->alloc_offset,
-				     &mips_data->boot_data_dma_addr));
+				     &fw_data->boot_data_dma_addr));
 	WARN_ON(pvr_gem_get_dma_addr(fw_dev->mem.code_obj->gem,
 				     exception_code_entry->alloc_offset,
-				     &mips_data->exception_code_dma_addr));
+				     &fw_data->exception_code_dma_addr));
 
 	stack_entry = pvr_fw_find_layout_entry(pvr_dev, MIPS_STACK);
 	if (!stack_entry)
@@ -76,14 +99,10 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 
 	boot_data->reg_base = pvr_dev->regs_resource->start;
 
-	for (u32 page_nr = 0; page_nr < ARRAY_SIZE(boot_data->pt_phys_addr); page_nr++) {
-		/* Firmware expects 4k pages, but host page size might be different. */
-		u32 src_page_nr = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) >> PAGE_SHIFT;
-		u32 page_offset = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) & ~PAGE_MASK;
-
-		boot_data->pt_phys_addr[page_nr] = mips_data->pt_dma_addr[src_page_nr] +
-						   page_offset;
-	}
+	err = pvr_vm_get_pt_phys_addrs(pvr_dev, boot_data->pt_phys_addr,
+				       ARRAY_SIZE(boot_data->pt_phys_addr));
+	if (err)
+		return err;
 
 	boot_data->pt_log2_page_size = ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
 	boot_data->pt_num_pages = ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES;
@@ -96,7 +115,7 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 static int
 pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 {
-	struct pvr_fw_mips_data *mips_data = pvr_dev->fw_dev.processor_data.mips_data;
+	struct pvr_fw_mips_data *fw_data = pvr_dev->fw_dev.processor_data.mips_data.fw_data;
 	const u64 remap_settings = ROGUE_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE;
 	u32 phys_bus_width;
 
@@ -119,7 +138,7 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 		       ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG2,
-		       (mips_data->boot_code_dma_addr &
+		       (fw_data->boot_code_dma_addr &
 			~ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings);
 
 	if (PVR_HAS_QUIRK(pvr_dev, 63553)) {
@@ -132,7 +151,7 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 		pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG1,
 			       ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG1_MODE_ENABLE_EN);
 		pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG2,
-			       (mips_data->boot_code_dma_addr &
+			       (fw_data->boot_code_dma_addr &
 				~ROGUE_CR_MIPS_ADDR_REMAP5_CONFIG2_ADDR_OUT_CLRMSK) |
 			       remap_settings);
 	}
@@ -141,14 +160,14 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 		       ROGUE_MIPSFW_DATA_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2,
-		       (mips_data->boot_data_dma_addr &
+		       (fw_data->boot_data_dma_addr &
 			~ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings);
 
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1,
 		       ROGUE_MIPSFW_CODE_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG2,
-		       (mips_data->exception_code_dma_addr &
+		       (fw_data->exception_code_dma_addr &
 			~ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings);
 
 	/* Garten IDLE bit controlled by MIPS. */
diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.h b/drivers/gpu/drm/imagination/pvr_fw_mips.h
deleted file mode 100644
index a0c5c41c8aa2..000000000000
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
-/* Copyright (c) 2023 Imagination Technologies Ltd. */
-
-#ifndef PVR_FW_MIPS_H
-#define PVR_FW_MIPS_H
-
-#include "pvr_rogue_mips.h"
-
-#include <asm/page.h>
-#include <linux/math.h>
-#include <linux/types.h>
-
-/* Forward declaration from pvr_gem.h. */
-struct pvr_gem_object;
-
-#define PVR_MIPS_PT_PAGE_COUNT DIV_ROUND_UP(ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
-
-/**
- * struct pvr_fw_mips_data - MIPS-specific data
- */
-struct pvr_fw_mips_data {
-	/**
-	 * @pt_pages: Pages containing MIPS pagetable.
-	 */
-	struct page *pt_pages[PVR_MIPS_PT_PAGE_COUNT];
-
-	/** @pt: Pointer to CPU mapping of MIPS pagetable. */
-	u32 *pt;
-
-	/** @pt_dma_addr: DMA mappings of MIPS pagetable. */
-	dma_addr_t pt_dma_addr[PVR_MIPS_PT_PAGE_COUNT];
-
-	/** @boot_code_dma_addr: DMA address of MIPS boot code. */
-	dma_addr_t boot_code_dma_addr;
-
-	/** @boot_data_dma_addr: DMA address of MIPS boot data. */
-	dma_addr_t boot_data_dma_addr;
-
-	/** @exception_code_dma_addr: DMA address of MIPS exception code. */
-	dma_addr_t exception_code_dma_addr;
-
-	/** @cache_policy: Cache policy for this processor. */
-	u32 cache_policy;
-
-	/** @pfn_mask: PFN mask for MIPS pagetable. */
-	u32 pfn_mask;
-};
-
-#endif /* PVR_FW_MIPS_H */
diff --git a/drivers/gpu/drm/imagination/pvr_fw_riscv.c b/drivers/gpu/drm/imagination/pvr_fw_riscv.c
index cd84635bb88d..612feb5e0ded 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_riscv.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_riscv.c
@@ -4,7 +4,6 @@
 #include "pvr_device.h"
 #include "pvr_fw.h"
 #include "pvr_fw_info.h"
-#include "pvr_fw_mips.h"
 #include "pvr_gem.h"
 #include "pvr_rogue_cr_defs.h"
 #include "pvr_rogue_riscv.h"
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_mips.h b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
similarity index 98%
rename from drivers/gpu/drm/imagination/pvr_rogue_mips.h
rename to drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
index 41ed618fda3f..68b4db83cb4b 100644
--- a/drivers/gpu/drm/imagination/pvr_rogue_mips.h
+++ b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
@@ -1,8 +1,12 @@
 /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
 /* Copyright (c) 2023 Imagination Technologies Ltd. */
 
-#ifndef PVR_ROGUE_MIPS_H
-#define PVR_ROGUE_MIPS_H
+#ifndef PVR_ROGUE_MIPS_INTERNAL_H
+#define PVR_ROGUE_MIPS_INTERNAL_H
+
+#ifndef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#error This file may only be included if explicitly defined
+#endif
 
 #include <linux/bits.h>
 #include <linux/types.h>
@@ -330,6 +334,6 @@ struct rogue_mips_state {
 	struct rogue_mips_remap_entry remap[ROGUE_MIPSFW_NUMBER_OF_REMAP_ENTRIES];
 };
 
-#include "pvr_rogue_mips_check.h"
+#include "pvr_rogue_mips_internal_check.h"
 
-#endif /* PVR_ROGUE_MIPS_H */
+#endif /* PVR_ROGUE_MIPS_INTERNAL_H */
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_mips_check.h b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
similarity index 91%
rename from drivers/gpu/drm/imagination/pvr_rogue_mips_check.h
rename to drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
index aebf231ce90f..60bc83d7cdbc 100644
--- a/drivers/gpu/drm/imagination/pvr_rogue_mips_check.h
+++ b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0-only OR MIT */
 /* Copyright (c) 2023 Imagination Technologies Ltd. */
 
-#ifndef PVR_ROGUE_MIPS_CHECK_H
-#define PVR_ROGUE_MIPS_CHECK_H
+#ifndef PVR_ROGUE_MIPS_INTERNAL_CHECK_H
+#define PVR_ROGUE_MIPS_INTERNAL_CHECK_H
 
 #include "pvr_check.h"
 
@@ -32,4 +32,4 @@ OFFSET_CHECK(struct rogue_mips_state, tlb, 44);
 OFFSET_CHECK(struct rogue_mips_state, remap, 300);
 SIZE_CHECK(struct rogue_mips_state, 684);
 
-#endif /* PVR_ROGUE_MIPS_CHECK_H */
+#endif /* PVR_ROGUE_MIPS_INTERNAL_CHECK_H */
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
index 5847a1c92bea..264ea0fccf9c 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
@@ -2,10 +2,11 @@
 /* Copyright (c) 2023 Imagination Technologies Ltd. */
 
 #include "pvr_device.h"
-#include "pvr_fw_mips.h"
 #include "pvr_gem.h"
 #include "pvr_mmu.h"
-#include "pvr_rogue_mips.h"
+#define PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#include "pvr_rogue_mips_internal.h"
+#undef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_vm.h"
 #include "pvr_vm_mips.h"
 
@@ -16,6 +17,31 @@
 #include <linux/types.h>
 #include <linux/vmalloc.h>
 
+#define PVR_MIPS_PT_PAGE_COUNT \
+	DIV_ROUND_UP(ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
+
+/**
+ * struct pvr_vm_mips_data - MIPS-VM-specific data
+ */
+struct pvr_vm_mips_data {
+	/**
+	 * @pt_pages: Pages containing MIPS pagetable.
+	 */
+	struct page *pt_pages[PVR_MIPS_PT_PAGE_COUNT];
+
+	/** @pt: Pointer to CPU mapping of MIPS pagetable. */
+	u32 *pt;
+
+	/** @pt_dma_addr: DMA mappings of MIPS pagetable. */
+	dma_addr_t pt_dma_addr[PVR_MIPS_PT_PAGE_COUNT];
+
+	/** @cache_policy: Cache policy for this processor. */
+	u32 cache_policy;
+
+	/** @pfn_mask: PFN mask for MIPS pagetable. */
+	u32 pfn_mask;
+};
+
 /**
  * pvr_vm_mips_init() - Initialise MIPS FW pagetable
  * @pvr_dev: Target PowerVR device.
@@ -31,7 +57,7 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)
 {
 	u32 pt_size = 1 << ROGUE_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev);
 	struct device *dev = from_pvr_device(pvr_dev)->dev;
-	struct pvr_fw_mips_data *mips_data;
+	struct pvr_vm_mips_data *vm_data;
 	u32 phys_bus_width;
 	int page_nr;
 	int err;
@@ -43,49 +69,49 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)
 	if (PVR_FEATURE_VALUE(pvr_dev, phys_bus_width, &phys_bus_width))
 		return -EINVAL;
 
-	mips_data = drmm_kzalloc(from_pvr_device(pvr_dev), sizeof(*mips_data), GFP_KERNEL);
-	if (!mips_data)
+	vm_data = drmm_kzalloc(from_pvr_device(pvr_dev), sizeof(*vm_data), GFP_KERNEL);
+	if (!vm_data)
 		return -ENOMEM;
 
 	for (page_nr = 0; page_nr < PVR_MIPS_PT_PAGE_COUNT; page_nr++) {
-		mips_data->pt_pages[page_nr] = alloc_page(GFP_KERNEL | __GFP_ZERO);
-		if (!mips_data->pt_pages[page_nr]) {
+		vm_data->pt_pages[page_nr] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (!vm_data->pt_pages[page_nr]) {
 			err = -ENOMEM;
 			goto err_free_pages;
 		}
 
-		mips_data->pt_dma_addr[page_nr] = dma_map_page(dev, mips_data->pt_pages[page_nr], 0,
-							       PAGE_SIZE, DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, mips_data->pt_dma_addr[page_nr])) {
+		vm_data->pt_dma_addr[page_nr] = dma_map_page(dev, vm_data->pt_pages[page_nr], 0,
+							     PAGE_SIZE, DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, vm_data->pt_dma_addr[page_nr])) {
 			err = -ENOMEM;
-			__free_page(mips_data->pt_pages[page_nr]);
+			__free_page(vm_data->pt_pages[page_nr]);
 			goto err_free_pages;
 		}
 	}
 
-	mips_data->pt = vmap(mips_data->pt_pages, pt_size >> PAGE_SHIFT, VM_MAP,
-			     pgprot_writecombine(PAGE_KERNEL));
-	if (!mips_data->pt) {
+	vm_data->pt = vmap(vm_data->pt_pages, pt_size >> PAGE_SHIFT, VM_MAP,
+			   pgprot_writecombine(PAGE_KERNEL));
+	if (!vm_data->pt) {
 		err = -ENOMEM;
 		goto err_free_pages;
 	}
 
-	mips_data->pfn_mask = (phys_bus_width > 32) ? ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
-						      ROGUE_MIPSFW_ENTRYLO_PFN_MASK;
+	vm_data->pfn_mask = (phys_bus_width > 32) ? ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
+						    ROGUE_MIPSFW_ENTRYLO_PFN_MASK;
 
-	mips_data->cache_policy = (phys_bus_width > 32) ? ROGUE_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
-							  ROGUE_MIPSFW_CACHED_POLICY;
+	vm_data->cache_policy = (phys_bus_width > 32) ? ROGUE_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
+							ROGUE_MIPSFW_CACHED_POLICY;
 
-	pvr_dev->fw_dev.processor_data.mips_data = mips_data;
+	pvr_dev->fw_dev.processor_data.mips_data.vm_data = vm_data;
 
 	return 0;
 
 err_free_pages:
 	while (--page_nr >= 0) {
 		dma_unmap_page(from_pvr_device(pvr_dev)->dev,
-			       mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
+			       vm_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
 
-		__free_page(mips_data->pt_pages[page_nr]);
+		__free_page(vm_data->pt_pages[page_nr]);
 	}
 
 	return err;
@@ -99,17 +125,17 @@ void
 pvr_vm_mips_fini(struct pvr_device *pvr_dev)
 {
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
-	struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
+	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
 
-	vunmap(mips_data->pt);
+	vunmap(vm_data->pt);
 	for (int page_nr = PVR_MIPS_PT_PAGE_COUNT - 1; page_nr >= 0; page_nr--) {
 		dma_unmap_page(from_pvr_device(pvr_dev)->dev,
-			       mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
+			       vm_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
 
-		__free_page(mips_data->pt_pages[page_nr]);
+		__free_page(vm_data->pt_pages[page_nr]);
 	}
 
-	fw_dev->processor_data.mips_data = NULL;
+	fw_dev->processor_data.mips_data.vm_data = NULL;
 }
 
 static u32
@@ -145,7 +171,7 @@ int
 pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 {
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
-	struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
+	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
 	struct pvr_gem_object *pvr_obj = fw_obj->gem;
 	const u64 start = fw_obj->fw_mm_node.start;
 	const u64 size = fw_obj->fw_mm_node.size;
@@ -174,7 +200,7 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 	if (pvr_obj->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
 		cache_policy = ROGUE_MIPSFW_UNCACHED_CACHE_POLICY;
 	else
-		cache_policy = mips_data->cache_policy;
+		cache_policy = vm_data->cache_policy;
 
 	pte_flags = get_mips_pte_flags(true, true, cache_policy);
 
@@ -190,10 +216,10 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 			goto err_unmap_pages;
 
 		pte = ((dma_addr >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-		       << ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT) & mips_data->pfn_mask;
+		       << ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT) & vm_data->pfn_mask;
 		pte |= pte_flags;
 
-		WRITE_ONCE(mips_data->pt[pfn], pte);
+		WRITE_ONCE(vm_data->pt[pfn], pte);
 	}
 
 	pvr_mmu_flush_request_all(pvr_dev);
@@ -202,7 +228,7 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 
 err_unmap_pages:
 	while (--pfn >= start_pfn)
-		WRITE_ONCE(mips_data->pt[pfn], 0);
+		WRITE_ONCE(vm_data->pt[pfn], 0);
 
 	pvr_mmu_flush_request_all(pvr_dev);
 	WARN_ON(pvr_mmu_flush_exec(pvr_dev, true));
@@ -219,7 +245,7 @@ void
 pvr_vm_mips_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 {
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
-	struct pvr_fw_mips_data *mips_data = fw_dev->processor_data.mips_data;
+	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
 	const u64 start = fw_obj->fw_mm_node.start;
 	const u64 size = fw_obj->fw_mm_node.size;
 	const u64 end = start + size;
@@ -230,8 +256,38 @@ pvr_vm_mips_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 			    ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
 
 	for (u32 pfn = start_pfn; pfn < end_pfn; pfn++)
-		WRITE_ONCE(mips_data->pt[pfn], 0);
+		WRITE_ONCE(vm_data->pt[pfn], 0);
 
 	pvr_mmu_flush_request_all(pvr_dev);
 	WARN_ON(pvr_mmu_flush_exec(pvr_dev, true));
 }
+
+/**
+ * pvr_vm_get_pt_phys_addrs() - Acquire the physical addresses of the MIPS FW page table pages
+ * @pvr_dev: Target PowerVR device.
+ * @phys_addrs: Output array for physical addresses of MIPS FW page table pages.
+ * @max_num_addrs: Maximum number of addresses that can be written to @phys_addrs.
+ *
+ * Returns:
+ *  * 0 on success, or
+ *  * -%EINVAL if @phys_addrs cannot accommodate all MIPS FW page table pages.
+ */
+int
+pvr_vm_get_pt_phys_addrs(struct pvr_device *pvr_dev, u64 *phys_addrs, int max_num_addrs)
+{
+	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
+	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
+
+	if (ARRAY_SIZE(vm_data->pt_pages) > max_num_addrs)
+		return -EINVAL;
+
+	for (u32 page_nr = 0; page_nr < max_num_addrs; page_nr++) {
+		/* Firmware expects 4k pages, but host page size might be different. */
+		u32 src_page_nr = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) >> PAGE_SHIFT;
+		u32 page_offset = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) & ~PAGE_MASK;
+
+		phys_addrs[page_nr] = vm_data->pt_dma_addr[src_page_nr] + page_offset;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.h b/drivers/gpu/drm/imagination/pvr_vm_mips.h
index 0fd59f68fb5b..3db0606c5037 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.h
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.h
@@ -18,5 +18,7 @@ int
 pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj);
 void
 pvr_vm_mips_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj);
+int
+pvr_vm_get_pt_phys_addrs(struct pvr_device *pvr_dev, u64 *phys_addrs, int max_num_addrs);
 
 #endif /* PVR_VM_MIPS_H */

-- 
2.43.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/4] drm/imagination: Make the MIPS firmware headers arch-independent
  2026-10-14  8:13 ` Alexandru Dadu
@ 2026-10-14  8:13   ` Alexandru Dadu
  -1 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu

From: Alessio Belle <alessio.belle@imgtec.com>

While this header is specific to Rogue, rename it and its contents
anyway with arch-independent prefixes for consistency with the other
firmware processor headers.

Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
 drivers/gpu/drm/imagination/pvr_fw_mips.c          |  28 +-
 drivers/gpu/drm/imagination/pvr_mips_internal.h    | 339 +++++++++++++++++++++
 .../gpu/drm/imagination/pvr_mips_internal_check.h  |  35 +++
 .../gpu/drm/imagination/pvr_rogue_mips_internal.h  | 339 ---------------------
 .../imagination/pvr_rogue_mips_internal_check.h    |  35 ---
 drivers/gpu/drm/imagination/pvr_vm_mips.c          |  54 ++--
 6 files changed, 415 insertions(+), 415 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 7e4dd23e1f3f..037f5cefe372 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -4,9 +4,9 @@
 #include "pvr_device.h"
 #include "pvr_fw.h"
 #include "pvr_gem.h"
-#define PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
-#include "pvr_rogue_mips_internal.h"
-#undef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#define PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#include "pvr_mips_internal.h"
+#undef PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_vm_mips.h"
 
 #include <linux/err.h>
@@ -63,7 +63,7 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 	const struct pvr_fw_layout_entry *boot_data_entry;
 	const struct pvr_fw_layout_entry *exception_code_entry;
 	const struct pvr_fw_layout_entry *stack_entry;
-	struct rogue_mipsfw_boot_data *boot_data;
+	struct pvr_mipsfw_boot_data *boot_data;
 	dma_addr_t dma_addr;
 	int err;
 
@@ -90,8 +90,8 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 	if (!stack_entry)
 		return -EINVAL;
 
-	boot_data = (struct rogue_mipsfw_boot_data *)(fw_data_ptr + boot_data_entry->alloc_offset +
-						      ROGUE_MIPSFW_BOOTLDR_CONF_OFFSET);
+	boot_data = (struct pvr_mipsfw_boot_data *)(fw_data_ptr + boot_data_entry->alloc_offset +
+						    PVR_MIPSFW_BOOTLDR_CONF_OFFSET);
 
 	WARN_ON(pvr_fw_object_get_dma_addr(fw_dev->mem.data_obj, stack_entry->alloc_offset,
 					   &dma_addr));
@@ -104,8 +104,8 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 	if (err)
 		return err;
 
-	boot_data->pt_log2_page_size = ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
-	boot_data->pt_num_pages = ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES;
+	boot_data->pt_log2_page_size = PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
+	boot_data->pt_num_pages = PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES;
 	boot_data->reserved1 = 0;
 	boot_data->reserved2 = 0;
 
@@ -116,7 +116,7 @@ static int
 pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 {
 	struct pvr_fw_mips_data *fw_data = pvr_dev->fw_dev.processor_data.mips_data.fw_data;
-	const u64 remap_settings = ROGUE_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE;
+	const u64 remap_settings = PVR_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE;
 	u32 phys_bus_width;
 
 	int err = PVR_FEATURE_VALUE(pvr_dev, phys_bus_width, &phys_bus_width);
@@ -129,13 +129,13 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 		return -EINVAL;
 
 	pvr_cr_write32(pvr_dev, ROGUE_CR_MIPS_WRAPPER_CONFIG,
-		       (ROGUE_MIPSFW_REGISTERS_VIRTUAL_BASE >>
-			ROGUE_MIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN) |
+		       (PVR_MIPSFW_REGISTERS_VIRTUAL_BASE >>
+			PVR_MIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN) |
 		       ROGUE_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS);
 
 	/* Configure remap for boot code, boot data and exceptions code areas. */
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG1,
-		       ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN |
+		       PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG2,
 		       (fw_data->boot_code_dma_addr &
@@ -157,14 +157,14 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 	}
 
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG1,
-		       ROGUE_MIPSFW_DATA_REMAP_PHYS_ADDR_IN |
+		       PVR_MIPSFW_DATA_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2,
 		       (fw_data->boot_data_dma_addr &
 			~ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings);
 
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1,
-		       ROGUE_MIPSFW_CODE_REMAP_PHYS_ADDR_IN |
+		       PVR_MIPSFW_CODE_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG2,
 		       (fw_data->exception_code_dma_addr &
diff --git a/drivers/gpu/drm/imagination/pvr_mips_internal.h b/drivers/gpu/drm/imagination/pvr_mips_internal.h
new file mode 100644
index 000000000000..732730d64bf5
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_mips_internal.h
@@ -0,0 +1,339 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/* Copyright (c) 2023 Imagination Technologies Ltd. */
+
+#ifndef PVR_MIPS_INTERNAL_H
+#define PVR_MIPS_INTERNAL_H
+
+#ifndef PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#error This file may only be included if explicitly defined
+#endif
+
+#include <linux/bits.h>
+#include <linux/types.h>
+
+/* Utility defines for memory management. */
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_4K (12)
+#define PVR_MIPSFW_PAGE_SIZE_4K (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
+#define PVR_MIPSFW_PAGE_MASK_4K (PVR_MIPSFW_PAGE_SIZE_4K - 1)
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_64K (16)
+#define PVR_MIPSFW_PAGE_SIZE_64K (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_64K)
+#define PVR_MIPSFW_PAGE_MASK_64K (PVR_MIPSFW_PAGE_SIZE_64K - 1)
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_256K (18)
+#define PVR_MIPSFW_PAGE_SIZE_256K (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_256K)
+#define PVR_MIPSFW_PAGE_MASK_256K (PVR_MIPSFW_PAGE_SIZE_256K - 1)
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_1MB (20)
+#define PVR_MIPSFW_PAGE_SIZE_1MB (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_1MB)
+#define PVR_MIPSFW_PAGE_MASK_1MB (PVR_MIPSFW_PAGE_SIZE_1MB - 1)
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_4MB (22)
+#define PVR_MIPSFW_PAGE_SIZE_4MB (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_4MB)
+#define PVR_MIPSFW_PAGE_MASK_4MB (PVR_MIPSFW_PAGE_SIZE_4MB - 1)
+#define PVR_MIPSFW_LOG2_PTE_ENTRY_SIZE (2)
+/* log2 page table sizes dependent on FW heap size and page size (for each OS). */
+#define PVR_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev) ((pvr_dev)->fw_dev.fw_heap_info.log2_size - \
+						    PVR_MIPSFW_LOG2_PAGE_SIZE_4K +    \
+						    PVR_MIPSFW_LOG2_PTE_ENTRY_SIZE)
+#define PVR_MIPSFW_LOG2_PAGETABLE_SIZE_64K(pvr_dev) ((pvr_dev)->fw_dev.fw_heap_info.log2_size - \
+						     PVR_MIPSFW_LOG2_PAGE_SIZE_64K +   \
+						     PVR_MIPSFW_LOG2_PTE_ENTRY_SIZE)
+/* Maximum number of page table pages (both Host and MIPS pages). */
+#define PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES (4)
+/* Total number of TLB entries. */
+#define PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES (16)
+/* "Uncached" caching policy. */
+#define PVR_MIPSFW_UNCACHED_CACHE_POLICY (2)
+/* "Write-back write-allocate" caching policy. */
+#define PVR_MIPSFW_WRITEBACK_CACHE_POLICY (3)
+/* "Write-through no write-allocate" caching policy. */
+#define PVR_MIPSFW_WRITETHROUGH_CACHE_POLICY (1)
+/* Cached policy used by MIPS in case of physical bus on 32 bit. */
+#define PVR_MIPSFW_CACHED_POLICY (PVR_MIPSFW_WRITEBACK_CACHE_POLICY)
+/* Cached policy used by MIPS in case of physical bus on more than 32 bit. */
+#define PVR_MIPSFW_CACHED_POLICY_ABOVE_32BIT (PVR_MIPSFW_WRITETHROUGH_CACHE_POLICY)
+/* Total number of Remap entries. */
+#define PVR_MIPSFW_NUMBER_OF_REMAP_ENTRIES (2 * PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES)
+
+/* MIPS EntryLo/PTE format. */
+
+#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_SHIFT (31U)
+#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_CLRMSK (0X7FFFFFFF)
+#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_EN (0X80000000)
+
+#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_SHIFT (30U)
+#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_CLRMSK (0XBFFFFFFF)
+#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_EN (0X40000000)
+
+/* Page Frame Number */
+#define PVR_MIPSFW_ENTRYLO_PFN_SHIFT (6)
+#define PVR_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT (12)
+/* Mask used for the MIPS Page Table in case of physical bus on 32 bit. */
+#define PVR_MIPSFW_ENTRYLO_PFN_MASK (0x03FFFFC0)
+#define PVR_MIPSFW_ENTRYLO_PFN_SIZE (20)
+/* Mask used for the MIPS Page Table in case of physical bus on more than 32 bit. */
+#define PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT (0x3FFFFFC0)
+#define PVR_MIPSFW_ENTRYLO_PFN_SIZE_ABOVE_32BIT (24)
+#define PVR_MIPSFW_ADDR_TO_ENTRYLO_PFN_RSHIFT (PVR_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT - \
+					       PVR_MIPSFW_ENTRYLO_PFN_SHIFT)
+
+#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT (3U)
+#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY_CLRMSK (0XFFFFFFC7)
+
+#define PVR_MIPSFW_ENTRYLO_DIRTY_SHIFT (2U)
+#define PVR_MIPSFW_ENTRYLO_DIRTY_CLRMSK (0XFFFFFFFB)
+#define PVR_MIPSFW_ENTRYLO_DIRTY_EN (0X00000004)
+
+#define PVR_MIPSFW_ENTRYLO_VALID_SHIFT (1U)
+#define PVR_MIPSFW_ENTRYLO_VALID_CLRMSK (0XFFFFFFFD)
+#define PVR_MIPSFW_ENTRYLO_VALID_EN (0X00000002)
+
+#define PVR_MIPSFW_ENTRYLO_GLOBAL_SHIFT (0U)
+#define PVR_MIPSFW_ENTRYLO_GLOBAL_CLRMSK (0XFFFFFFFE)
+#define PVR_MIPSFW_ENTRYLO_GLOBAL_EN (0X00000001)
+
+#define PVR_MIPSFW_ENTRYLO_DVG (PVR_MIPSFW_ENTRYLO_DIRTY_EN | \
+				PVR_MIPSFW_ENTRYLO_VALID_EN | \
+				PVR_MIPSFW_ENTRYLO_GLOBAL_EN)
+#define PVR_MIPSFW_ENTRYLO_UNCACHED (PVR_MIPSFW_UNCACHED_CACHE_POLICY << \
+				     PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT)
+#define PVR_MIPSFW_ENTRYLO_DVG_UNCACHED (PVR_MIPSFW_ENTRYLO_DVG | \
+					 PVR_MIPSFW_ENTRYLO_UNCACHED)
+
+/* Remap Range Config Addr Out. */
+/* These defines refer to the upper half of the Remap Range Config register. */
+#define PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_MASK (0x0FFFFFF0)
+#define PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_SHIFT (4) /* wrt upper half of the register. */
+#define PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_ALIGNSHIFT (12)
+#define PVR_MIPSFW_ADDR_TO_RR_ADDR_OUT_RSHIFT (PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_ALIGNSHIFT - \
+					       PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_SHIFT)
+
+/*
+ * Pages to trampoline problematic physical addresses:
+ *   - PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN : 0x1FC0_0000
+ *   - PVR_MIPSFW_DATA_REMAP_PHYS_ADDR_IN : 0x1FC0_1000
+ *   - PVR_MIPSFW_CODE_REMAP_PHYS_ADDR_IN : 0x1FC0_2000
+ *   - (benign trampoline)               : 0x1FC0_3000
+ * that would otherwise be erroneously remapped by the MIPS wrapper.
+ * (see "Firmware virtual layout and remap configuration" section below)
+ */
+
+#define PVR_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES (2)
+#define PVR_MIPSFW_TRAMPOLINE_NUMPAGES BIT(PVR_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES)
+#define PVR_MIPSFW_TRAMPOLINE_SIZE (PVR_MIPSFW_TRAMPOLINE_NUMPAGES << \
+				    PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
+#define PVR_MIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE (PVR_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES + \
+						 PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
+
+#define PVR_MIPSFW_TRAMPOLINE_TARGET_PHYS_ADDR (PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
+#define PVR_MIPSFW_TRAMPOLINE_OFFSET(a) ((a) - PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
+
+#define PVR_MIPSFW_SENSITIVE_ADDR(a) (PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN == \
+				      (~((1 << PVR_MIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE) - 1) \
+				       & (a)))
+
+/* Firmware virtual layout and remap configuration. */
+/*
+ * For each remap region we define:
+ * - the virtual base used by the Firmware to access code/data through that region
+ * - the microAptivAP physical address correspondent to the virtual base address,
+ *   used as input address and remapped to the actual physical address
+ * - log2 of size of the region remapped by the MIPS wrapper, i.e. number of bits from
+ *   the bottom of the base input address that survive onto the output address
+ *   (this defines both the alignment and the maximum size of the remapped region)
+ * - one or more code/data segments within the remapped region.
+ */
+
+/* Boot remap setup. */
+#define PVR_MIPSFW_BOOT_REMAP_VIRTUAL_BASE (0xBFC00000)
+#define PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN (0x1FC00000)
+#define PVR_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE (12)
+#define PVR_MIPSFW_BOOT_NMI_CODE_VIRTUAL_BASE (PVR_MIPSFW_BOOT_REMAP_VIRTUAL_BASE)
+
+/* Data remap setup. */
+#define PVR_MIPSFW_DATA_REMAP_VIRTUAL_BASE (0xBFC01000)
+#define PVR_MIPSFW_DATA_CACHED_REMAP_VIRTUAL_BASE (0x9FC01000)
+#define PVR_MIPSFW_DATA_REMAP_PHYS_ADDR_IN (0x1FC01000)
+#define PVR_MIPSFW_DATA_REMAP_LOG2_SEGMENT_SIZE (12)
+#define PVR_MIPSFW_BOOT_NMI_DATA_VIRTUAL_BASE (PVR_MIPSFW_DATA_REMAP_VIRTUAL_BASE)
+
+/* Code remap setup. */
+#define PVR_MIPSFW_CODE_REMAP_VIRTUAL_BASE (0x9FC02000)
+#define PVR_MIPSFW_CODE_REMAP_PHYS_ADDR_IN (0x1FC02000)
+#define PVR_MIPSFW_CODE_REMAP_LOG2_SEGMENT_SIZE (12)
+#define PVR_MIPSFW_EXCEPTIONS_VIRTUAL_BASE (PVR_MIPSFW_CODE_REMAP_VIRTUAL_BASE)
+
+/* Permanent mappings setup. */
+#define PVR_MIPSFW_PT_VIRTUAL_BASE (0xCF000000)
+#define PVR_MIPSFW_REGISTERS_VIRTUAL_BASE (0xCF800000)
+#define PVR_MIPSFW_STACK_VIRTUAL_BASE (0xCF600000)
+
+/* Bootloader configuration data. */
+/*
+ * Bootloader configuration offset (where PVR_MIPSFW_BOOT_DATA lives)
+ * within the bootloader/NMI data page.
+ */
+#define PVR_MIPSFW_BOOTLDR_CONF_OFFSET (0x0)
+
+/* NMI shared data. */
+/* Base address of the shared data within the bootloader/NMI data page. */
+#define PVR_MIPSFW_NMI_SHARED_DATA_BASE (0x100)
+/* Size used by Debug dump data. */
+#define PVR_MIPSFW_NMI_SHARED_SIZE (0x2B0)
+/* Offsets in the NMI shared area in 32-bit words. */
+#define PVR_MIPSFW_NMI_SYNC_FLAG_OFFSET (0x0)
+#define PVR_MIPSFW_NMI_STATE_OFFSET (0x1)
+#define PVR_MIPSFW_NMI_ERROR_STATE_SET (0x1)
+
+/* MIPS boot stage. */
+#define PVR_MIPSFW_BOOT_STAGE_OFFSET (0x400)
+
+/*
+ * MIPS private data in the bootloader data page.
+ * Memory below this offset is used by the FW only, no interface data allowed.
+ */
+#define PVR_MIPSFW_PRIVATE_DATA_OFFSET (0x800)
+
+struct pvr_mipsfw_boot_data {
+	u64 stack_phys_addr;
+	u64 reg_base;
+	u64 pt_phys_addr[PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES];
+	u32 pt_log2_page_size;
+	u32 pt_num_pages;
+	u32 reserved1;
+	u32 reserved2;
+};
+
+#define PVR_MIPSFW_GET_OFFSET_IN_DWORDS(offset) ((offset) / sizeof(u32))
+#define PVR_MIPSFW_GET_OFFSET_IN_QWORDS(offset) ((offset) / sizeof(u64))
+
+/* Used for compatibility checks. */
+#define PVR_MIPSFW_ARCHTYPE_VER_CLRMSK (0xFFFFE3FFU)
+#define PVR_MIPSFW_ARCHTYPE_VER_SHIFT (10U)
+#define PVR_MIPSFW_CORE_ID_VALUE (0x001U)
+#define PVR_FW_PROCESSOR_MIPS "MIPS"
+
+/* microAptivAP cache line size. */
+#define PVR_MIPSFW_MICROAPTIVEAP_CACHELINE_SIZE (16U)
+
+/*
+ * The SOCIF transactions are identified with the top 16 bits of the physical address emitted by
+ * the MIPS.
+ */
+#define PVR_MIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN (16U)
+
+/* Values to put in the MIPS selectors for performance counters. */
+/* Icache accesses in COUNTER0. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_ICACHE_ACCESSES_C0 (9U)
+/* Icache misses in COUNTER1. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_ICACHE_MISSES_C1 (9U)
+
+/* Dcache accesses in COUNTER0. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_DCACHE_ACCESSES_C0 (10U)
+/* Dcache misses in COUNTER1. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_DCACHE_MISSES_C1 (11U)
+
+/* ITLB instruction accesses in COUNTER0. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_ITLB_INSTR_ACCESSES_C0 (5U)
+/* JTLB instruction accesses misses in COUNTER1. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_JTLB_INSTR_MISSES_C1 (7U)
+
+  /* Instructions completed in COUNTER0. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_INSTR_COMPLETED_C0 (1U)
+/* JTLB data misses in COUNTER1. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_JTLB_DATA_MISSES_C1 (8U)
+
+/* Shift for the Event field in the MIPS perf ctrl registers. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_EVENT_SHIFT (5U)
+
+/* Additional flags for performance counters. See MIPS manual for further reference. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_COUNT_USER_MODE (8U)
+#define PVR_MIPSFW_PERF_COUNT_CTRL_COUNT_KERNEL_MODE (2U)
+#define PVR_MIPSFW_PERF_COUNT_CTRL_COUNT_EXL (1U)
+
+#define PVR_MIPSFW_C0_NBHWIRQ	8
+
+/* Macros to decode C0_Cause register. */
+#define PVR_MIPSFW_C0_CAUSE_EXCCODE(cause) (((cause) & 0x7c) >> 2)
+#define PVR_MIPSFW_C0_CAUSE_EXCCODE_FWERROR 9
+/* Use only when Coprocessor Unusable exception. */
+#define PVR_MIPSFW_C0_CAUSE_UNUSABLE_UNIT(cause) (((cause) >> 28) & 0x3)
+#define PVR_MIPSFW_C0_CAUSE_PENDING_HWIRQ(cause) (((cause) & 0x3fc00) >> 10)
+#define PVR_MIPSFW_C0_CAUSE_FDCIPENDING BIT(21)
+#define PVR_MIPSFW_C0_CAUSE_IV BIT(23)
+#define PVR_MIPSFW_C0_CAUSE_IC BIT(25)
+#define PVR_MIPSFW_C0_CAUSE_PCIPENDING BIT(26)
+#define PVR_MIPSFW_C0_CAUSE_TIPENDING BIT(30)
+#define PVR_MIPSFW_C0_CAUSE_BRANCH_DELAY BIT(31)
+
+/* Macros to decode C0_Debug register. */
+#define PVR_MIPSFW_C0_DEBUG_EXCCODE(debug) (((debug) >> 10) & 0x1f)
+#define PVR_MIPSFW_C0_DEBUG_DSS BIT(0)
+#define PVR_MIPSFW_C0_DEBUG_DBP BIT(1)
+#define PVR_MIPSFW_C0_DEBUG_DDBL BIT(2)
+#define PVR_MIPSFW_C0_DEBUG_DDBS BIT(3)
+#define PVR_MIPSFW_C0_DEBUG_DIB BIT(4)
+#define PVR_MIPSFW_C0_DEBUG_DINT BIT(5)
+#define PVR_MIPSFW_C0_DEBUG_DIBIMPR BIT(6)
+#define PVR_MIPSFW_C0_DEBUG_DDBLIMPR BIT(18)
+#define PVR_MIPSFW_C0_DEBUG_DDBSIMPR BIT(19)
+#define PVR_MIPSFW_C0_DEBUG_IEXI BIT(20)
+#define PVR_MIPSFW_C0_DEBUG_DBUSEP BIT(21)
+#define PVR_MIPSFW_C0_DEBUG_CACHEEP BIT(22)
+#define PVR_MIPSFW_C0_DEBUG_MCHECKP BIT(23)
+#define PVR_MIPSFW_C0_DEBUG_IBUSEP BIT(24)
+#define PVR_MIPSFW_C0_DEBUG_DM BIT(30)
+#define PVR_MIPSFW_C0_DEBUG_DBD BIT(31)
+
+/* Macros to decode TLB entries. */
+#define PVR_MIPSFW_TLB_GET_MASK(page_mask) (((page_mask) >> 13) & 0XFFFFU)
+/* Page size in KB. */
+#define PVR_MIPSFW_TLB_GET_PAGE_SIZE(page_mask) ((((page_mask) | 0x1FFF) + 1) >> 11)
+/* Page size in KB. */
+#define PVR_MIPSFW_TLB_GET_PAGE_MASK(page_size) ((((page_size) << 11) - 1) & ~0x7FF)
+#define PVR_MIPSFW_TLB_GET_VPN2(entry_hi) ((entry_hi) >> 13)
+#define PVR_MIPSFW_TLB_GET_COHERENCY(entry_lo) (((entry_lo) >> 3) & 0x7U)
+#define PVR_MIPSFW_TLB_GET_PFN(entry_lo) (((entry_lo) >> 6) & 0XFFFFFU)
+/* GET_PA uses a non-standard PFN mask for 36 bit addresses. */
+#define PVR_MIPSFW_TLB_GET_PA(entry_lo) (((u64)(entry_lo) & \
+					  PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT) << 6)
+#define PVR_MIPSFW_TLB_GET_INHIBIT(entry_lo) (((entry_lo) >> 30) & 0x3U)
+#define PVR_MIPSFW_TLB_GET_DGV(entry_lo) ((entry_lo) & 0x7U)
+#define PVR_MIPSFW_TLB_GLOBAL BIT(0)
+#define PVR_MIPSFW_TLB_VALID BIT(1)
+#define PVR_MIPSFW_TLB_DIRTY BIT(2)
+#define PVR_MIPSFW_TLB_XI BIT(30)
+#define PVR_MIPSFW_TLB_RI BIT(31)
+
+#define PVR_MIPSFW_REMAP_GET_REGION_SIZE(region_size_encoding) (1 << (((region_size_encoding) \
+								      + 1) << 1))
+
+struct pvr_mips_tlb_entry {
+	u32 tlb_page_mask;
+	u32 tlb_hi;
+	u32 tlb_lo0;
+	u32 tlb_lo1;
+};
+
+struct pvr_mips_remap_entry {
+	u32 remap_addr_in;  /* Always 4k aligned. */
+	u32 remap_addr_out; /* Always 4k aligned. */
+	u32 remap_region_size;
+};
+
+struct pvr_mips_state {
+	u32 error_state; /* This must come first in the structure. */
+	u32 error_epc;
+	u32 status_register;
+	u32 cause_register;
+	u32 bad_register;
+	u32 epc;
+	u32 sp;
+	u32 debug;
+	u32 depc;
+	u32 bad_instr;
+	u32 unmapped_address;
+	struct pvr_mips_tlb_entry tlb[PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES];
+	struct pvr_mips_remap_entry remap[PVR_MIPSFW_NUMBER_OF_REMAP_ENTRIES];
+};
+
+#include "pvr_mips_internal_check.h"
+
+#endif /* PVR_MIPS_INTERNAL_H */
diff --git a/drivers/gpu/drm/imagination/pvr_mips_internal_check.h b/drivers/gpu/drm/imagination/pvr_mips_internal_check.h
new file mode 100644
index 000000000000..7583a34bfc72
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_mips_internal_check.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/* Copyright (c) 2023 Imagination Technologies Ltd. */
+
+#ifndef PVR_MIPS_INTERNAL_CHECK_H
+#define PVR_MIPS_INTERNAL_CHECK_H
+
+#include "pvr_check.h"
+
+OFFSET_CHECK(struct pvr_mips_tlb_entry, tlb_page_mask, 0);
+OFFSET_CHECK(struct pvr_mips_tlb_entry, tlb_hi, 4);
+OFFSET_CHECK(struct pvr_mips_tlb_entry, tlb_lo0, 8);
+OFFSET_CHECK(struct pvr_mips_tlb_entry, tlb_lo1, 12);
+SIZE_CHECK(struct pvr_mips_tlb_entry, 16);
+
+OFFSET_CHECK(struct pvr_mips_remap_entry, remap_addr_in, 0);
+OFFSET_CHECK(struct pvr_mips_remap_entry, remap_addr_out, 4);
+OFFSET_CHECK(struct pvr_mips_remap_entry, remap_region_size, 8);
+SIZE_CHECK(struct pvr_mips_remap_entry, 12);
+
+OFFSET_CHECK(struct pvr_mips_state, error_state, 0);
+OFFSET_CHECK(struct pvr_mips_state, error_epc, 4);
+OFFSET_CHECK(struct pvr_mips_state, status_register, 8);
+OFFSET_CHECK(struct pvr_mips_state, cause_register, 12);
+OFFSET_CHECK(struct pvr_mips_state, bad_register, 16);
+OFFSET_CHECK(struct pvr_mips_state, epc, 20);
+OFFSET_CHECK(struct pvr_mips_state, sp, 24);
+OFFSET_CHECK(struct pvr_mips_state, debug, 28);
+OFFSET_CHECK(struct pvr_mips_state, depc, 32);
+OFFSET_CHECK(struct pvr_mips_state, bad_instr, 36);
+OFFSET_CHECK(struct pvr_mips_state, unmapped_address, 40);
+OFFSET_CHECK(struct pvr_mips_state, tlb, 44);
+OFFSET_CHECK(struct pvr_mips_state, remap, 300);
+SIZE_CHECK(struct pvr_mips_state, 684);
+
+#endif /* PVR_MIPS_INTERNAL_CHECK_H */
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
deleted file mode 100644
index 68b4db83cb4b..000000000000
--- a/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
-/* Copyright (c) 2023 Imagination Technologies Ltd. */
-
-#ifndef PVR_ROGUE_MIPS_INTERNAL_H
-#define PVR_ROGUE_MIPS_INTERNAL_H
-
-#ifndef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
-#error This file may only be included if explicitly defined
-#endif
-
-#include <linux/bits.h>
-#include <linux/types.h>
-
-/* Utility defines for memory management. */
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K (12)
-#define ROGUE_MIPSFW_PAGE_SIZE_4K (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-#define ROGUE_MIPSFW_PAGE_MASK_4K (ROGUE_MIPSFW_PAGE_SIZE_4K - 1)
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_64K (16)
-#define ROGUE_MIPSFW_PAGE_SIZE_64K (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_64K)
-#define ROGUE_MIPSFW_PAGE_MASK_64K (ROGUE_MIPSFW_PAGE_SIZE_64K - 1)
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_256K (18)
-#define ROGUE_MIPSFW_PAGE_SIZE_256K (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_256K)
-#define ROGUE_MIPSFW_PAGE_MASK_256K (ROGUE_MIPSFW_PAGE_SIZE_256K - 1)
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_1MB (20)
-#define ROGUE_MIPSFW_PAGE_SIZE_1MB (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_1MB)
-#define ROGUE_MIPSFW_PAGE_MASK_1MB (ROGUE_MIPSFW_PAGE_SIZE_1MB - 1)
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_4MB (22)
-#define ROGUE_MIPSFW_PAGE_SIZE_4MB (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_4MB)
-#define ROGUE_MIPSFW_PAGE_MASK_4MB (ROGUE_MIPSFW_PAGE_SIZE_4MB - 1)
-#define ROGUE_MIPSFW_LOG2_PTE_ENTRY_SIZE (2)
-/* log2 page table sizes dependent on FW heap size and page size (for each OS). */
-#define ROGUE_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev) ((pvr_dev)->fw_dev.fw_heap_info.log2_size - \
-						      ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K +    \
-						      ROGUE_MIPSFW_LOG2_PTE_ENTRY_SIZE)
-#define ROGUE_MIPSFW_LOG2_PAGETABLE_SIZE_64K(pvr_dev) ((pvr_dev)->fw_dev.fw_heap_info.log2_size - \
-						       ROGUE_MIPSFW_LOG2_PAGE_SIZE_64K +   \
-						       ROGUE_MIPSFW_LOG2_PTE_ENTRY_SIZE)
-/* Maximum number of page table pages (both Host and MIPS pages). */
-#define ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES (4)
-/* Total number of TLB entries. */
-#define ROGUE_MIPSFW_NUMBER_OF_TLB_ENTRIES (16)
-/* "Uncached" caching policy. */
-#define ROGUE_MIPSFW_UNCACHED_CACHE_POLICY (2)
-/* "Write-back write-allocate" caching policy. */
-#define ROGUE_MIPSFW_WRITEBACK_CACHE_POLICY (3)
-/* "Write-through no write-allocate" caching policy. */
-#define ROGUE_MIPSFW_WRITETHROUGH_CACHE_POLICY (1)
-/* Cached policy used by MIPS in case of physical bus on 32 bit. */
-#define ROGUE_MIPSFW_CACHED_POLICY (ROGUE_MIPSFW_WRITEBACK_CACHE_POLICY)
-/* Cached policy used by MIPS in case of physical bus on more than 32 bit. */
-#define ROGUE_MIPSFW_CACHED_POLICY_ABOVE_32BIT (ROGUE_MIPSFW_WRITETHROUGH_CACHE_POLICY)
-/* Total number of Remap entries. */
-#define ROGUE_MIPSFW_NUMBER_OF_REMAP_ENTRIES (2 * ROGUE_MIPSFW_NUMBER_OF_TLB_ENTRIES)
-
-/* MIPS EntryLo/PTE format. */
-
-#define ROGUE_MIPSFW_ENTRYLO_READ_INHIBIT_SHIFT (31U)
-#define ROGUE_MIPSFW_ENTRYLO_READ_INHIBIT_CLRMSK (0X7FFFFFFF)
-#define ROGUE_MIPSFW_ENTRYLO_READ_INHIBIT_EN (0X80000000)
-
-#define ROGUE_MIPSFW_ENTRYLO_EXEC_INHIBIT_SHIFT (30U)
-#define ROGUE_MIPSFW_ENTRYLO_EXEC_INHIBIT_CLRMSK (0XBFFFFFFF)
-#define ROGUE_MIPSFW_ENTRYLO_EXEC_INHIBIT_EN (0X40000000)
-
-/* Page Frame Number */
-#define ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT (6)
-#define ROGUE_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT (12)
-/* Mask used for the MIPS Page Table in case of physical bus on 32 bit. */
-#define ROGUE_MIPSFW_ENTRYLO_PFN_MASK (0x03FFFFC0)
-#define ROGUE_MIPSFW_ENTRYLO_PFN_SIZE (20)
-/* Mask used for the MIPS Page Table in case of physical bus on more than 32 bit. */
-#define ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT (0x3FFFFFC0)
-#define ROGUE_MIPSFW_ENTRYLO_PFN_SIZE_ABOVE_32BIT (24)
-#define ROGUE_MIPSFW_ADDR_TO_ENTRYLO_PFN_RSHIFT (ROGUE_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT - \
-						 ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT)
-
-#define ROGUE_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT (3U)
-#define ROGUE_MIPSFW_ENTRYLO_CACHE_POLICY_CLRMSK (0XFFFFFFC7)
-
-#define ROGUE_MIPSFW_ENTRYLO_DIRTY_SHIFT (2U)
-#define ROGUE_MIPSFW_ENTRYLO_DIRTY_CLRMSK (0XFFFFFFFB)
-#define ROGUE_MIPSFW_ENTRYLO_DIRTY_EN (0X00000004)
-
-#define ROGUE_MIPSFW_ENTRYLO_VALID_SHIFT (1U)
-#define ROGUE_MIPSFW_ENTRYLO_VALID_CLRMSK (0XFFFFFFFD)
-#define ROGUE_MIPSFW_ENTRYLO_VALID_EN (0X00000002)
-
-#define ROGUE_MIPSFW_ENTRYLO_GLOBAL_SHIFT (0U)
-#define ROGUE_MIPSFW_ENTRYLO_GLOBAL_CLRMSK (0XFFFFFFFE)
-#define ROGUE_MIPSFW_ENTRYLO_GLOBAL_EN (0X00000001)
-
-#define ROGUE_MIPSFW_ENTRYLO_DVG (ROGUE_MIPSFW_ENTRYLO_DIRTY_EN | \
-				  ROGUE_MIPSFW_ENTRYLO_VALID_EN | \
-				  ROGUE_MIPSFW_ENTRYLO_GLOBAL_EN)
-#define ROGUE_MIPSFW_ENTRYLO_UNCACHED (ROGUE_MIPSFW_UNCACHED_CACHE_POLICY << \
-				       ROGUE_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT)
-#define ROGUE_MIPSFW_ENTRYLO_DVG_UNCACHED (ROGUE_MIPSFW_ENTRYLO_DVG | \
-					   ROGUE_MIPSFW_ENTRYLO_UNCACHED)
-
-/* Remap Range Config Addr Out. */
-/* These defines refer to the upper half of the Remap Range Config register. */
-#define ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_MASK (0x0FFFFFF0)
-#define ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_SHIFT (4) /* wrt upper half of the register. */
-#define ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_ALIGNSHIFT (12)
-#define ROGUE_MIPSFW_ADDR_TO_RR_ADDR_OUT_RSHIFT (ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_ALIGNSHIFT - \
-						 ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_SHIFT)
-
-/*
- * Pages to trampoline problematic physical addresses:
- *   - ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN : 0x1FC0_0000
- *   - ROGUE_MIPSFW_DATA_REMAP_PHYS_ADDR_IN : 0x1FC0_1000
- *   - ROGUE_MIPSFW_CODE_REMAP_PHYS_ADDR_IN : 0x1FC0_2000
- *   - (benign trampoline)               : 0x1FC0_3000
- * that would otherwise be erroneously remapped by the MIPS wrapper.
- * (see "Firmware virtual layout and remap configuration" section below)
- */
-
-#define ROGUE_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES (2)
-#define ROGUE_MIPSFW_TRAMPOLINE_NUMPAGES BIT(ROGUE_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES)
-#define ROGUE_MIPSFW_TRAMPOLINE_SIZE (ROGUE_MIPSFW_TRAMPOLINE_NUMPAGES << \
-				      ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-#define ROGUE_MIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE (ROGUE_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES + \
-						   ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-
-#define ROGUE_MIPSFW_TRAMPOLINE_TARGET_PHYS_ADDR (ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
-#define ROGUE_MIPSFW_TRAMPOLINE_OFFSET(a) ((a) - ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
-
-#define ROGUE_MIPSFW_SENSITIVE_ADDR(a) (ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN == \
-					(~((1 << ROGUE_MIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE) - 1) \
-					 & (a)))
-
-/* Firmware virtual layout and remap configuration. */
-/*
- * For each remap region we define:
- * - the virtual base used by the Firmware to access code/data through that region
- * - the microAptivAP physical address correspondent to the virtual base address,
- *   used as input address and remapped to the actual physical address
- * - log2 of size of the region remapped by the MIPS wrapper, i.e. number of bits from
- *   the bottom of the base input address that survive onto the output address
- *   (this defines both the alignment and the maximum size of the remapped region)
- * - one or more code/data segments within the remapped region.
- */
-
-/* Boot remap setup. */
-#define ROGUE_MIPSFW_BOOT_REMAP_VIRTUAL_BASE (0xBFC00000)
-#define ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN (0x1FC00000)
-#define ROGUE_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE (12)
-#define ROGUE_MIPSFW_BOOT_NMI_CODE_VIRTUAL_BASE (ROGUE_MIPSFW_BOOT_REMAP_VIRTUAL_BASE)
-
-/* Data remap setup. */
-#define ROGUE_MIPSFW_DATA_REMAP_VIRTUAL_BASE (0xBFC01000)
-#define ROGUE_MIPSFW_DATA_CACHED_REMAP_VIRTUAL_BASE (0x9FC01000)
-#define ROGUE_MIPSFW_DATA_REMAP_PHYS_ADDR_IN (0x1FC01000)
-#define ROGUE_MIPSFW_DATA_REMAP_LOG2_SEGMENT_SIZE (12)
-#define ROGUE_MIPSFW_BOOT_NMI_DATA_VIRTUAL_BASE (ROGUE_MIPSFW_DATA_REMAP_VIRTUAL_BASE)
-
-/* Code remap setup. */
-#define ROGUE_MIPSFW_CODE_REMAP_VIRTUAL_BASE (0x9FC02000)
-#define ROGUE_MIPSFW_CODE_REMAP_PHYS_ADDR_IN (0x1FC02000)
-#define ROGUE_MIPSFW_CODE_REMAP_LOG2_SEGMENT_SIZE (12)
-#define ROGUE_MIPSFW_EXCEPTIONS_VIRTUAL_BASE (ROGUE_MIPSFW_CODE_REMAP_VIRTUAL_BASE)
-
-/* Permanent mappings setup. */
-#define ROGUE_MIPSFW_PT_VIRTUAL_BASE (0xCF000000)
-#define ROGUE_MIPSFW_REGISTERS_VIRTUAL_BASE (0xCF800000)
-#define ROGUE_MIPSFW_STACK_VIRTUAL_BASE (0xCF600000)
-
-/* Bootloader configuration data. */
-/*
- * Bootloader configuration offset (where ROGUE_MIPSFW_BOOT_DATA lives)
- * within the bootloader/NMI data page.
- */
-#define ROGUE_MIPSFW_BOOTLDR_CONF_OFFSET (0x0)
-
-/* NMI shared data. */
-/* Base address of the shared data within the bootloader/NMI data page. */
-#define ROGUE_MIPSFW_NMI_SHARED_DATA_BASE (0x100)
-/* Size used by Debug dump data. */
-#define ROGUE_MIPSFW_NMI_SHARED_SIZE (0x2B0)
-/* Offsets in the NMI shared area in 32-bit words. */
-#define ROGUE_MIPSFW_NMI_SYNC_FLAG_OFFSET (0x0)
-#define ROGUE_MIPSFW_NMI_STATE_OFFSET (0x1)
-#define ROGUE_MIPSFW_NMI_ERROR_STATE_SET (0x1)
-
-/* MIPS boot stage. */
-#define ROGUE_MIPSFW_BOOT_STAGE_OFFSET (0x400)
-
-/*
- * MIPS private data in the bootloader data page.
- * Memory below this offset is used by the FW only, no interface data allowed.
- */
-#define ROGUE_MIPSFW_PRIVATE_DATA_OFFSET (0x800)
-
-struct rogue_mipsfw_boot_data {
-	u64 stack_phys_addr;
-	u64 reg_base;
-	u64 pt_phys_addr[ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES];
-	u32 pt_log2_page_size;
-	u32 pt_num_pages;
-	u32 reserved1;
-	u32 reserved2;
-};
-
-#define ROGUE_MIPSFW_GET_OFFSET_IN_DWORDS(offset) ((offset) / sizeof(u32))
-#define ROGUE_MIPSFW_GET_OFFSET_IN_QWORDS(offset) ((offset) / sizeof(u64))
-
-/* Used for compatibility checks. */
-#define ROGUE_MIPSFW_ARCHTYPE_VER_CLRMSK (0xFFFFE3FFU)
-#define ROGUE_MIPSFW_ARCHTYPE_VER_SHIFT (10U)
-#define ROGUE_MIPSFW_CORE_ID_VALUE (0x001U)
-#define ROGUE_FW_PROCESSOR_MIPS "MIPS"
-
-/* microAptivAP cache line size. */
-#define ROGUE_MIPSFW_MICROAPTIVEAP_CACHELINE_SIZE (16U)
-
-/*
- * The SOCIF transactions are identified with the top 16 bits of the physical address emitted by
- * the MIPS.
- */
-#define ROGUE_MIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN (16U)
-
-/* Values to put in the MIPS selectors for performance counters. */
-/* Icache accesses in COUNTER0. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_ICACHE_ACCESSES_C0 (9U)
-/* Icache misses in COUNTER1. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_ICACHE_MISSES_C1 (9U)
-
-/* Dcache accesses in COUNTER0. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_DCACHE_ACCESSES_C0 (10U)
-/* Dcache misses in COUNTER1. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_DCACHE_MISSES_C1 (11U)
-
-/* ITLB instruction accesses in COUNTER0. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_ITLB_INSTR_ACCESSES_C0 (5U)
-/* JTLB instruction accesses misses in COUNTER1. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_JTLB_INSTR_MISSES_C1 (7U)
-
-  /* Instructions completed in COUNTER0. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_INSTR_COMPLETED_C0 (1U)
-/* JTLB data misses in COUNTER1. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_JTLB_DATA_MISSES_C1 (8U)
-
-/* Shift for the Event field in the MIPS perf ctrl registers. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_EVENT_SHIFT (5U)
-
-/* Additional flags for performance counters. See MIPS manual for further reference. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_COUNT_USER_MODE (8U)
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_COUNT_KERNEL_MODE (2U)
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_COUNT_EXL (1U)
-
-#define ROGUE_MIPSFW_C0_NBHWIRQ	8
-
-/* Macros to decode C0_Cause register. */
-#define ROGUE_MIPSFW_C0_CAUSE_EXCCODE(cause) (((cause) & 0x7c) >> 2)
-#define ROGUE_MIPSFW_C0_CAUSE_EXCCODE_FWERROR 9
-/* Use only when Coprocessor Unusable exception. */
-#define ROGUE_MIPSFW_C0_CAUSE_UNUSABLE_UNIT(cause) (((cause) >> 28) & 0x3)
-#define ROGUE_MIPSFW_C0_CAUSE_PENDING_HWIRQ(cause) (((cause) & 0x3fc00) >> 10)
-#define ROGUE_MIPSFW_C0_CAUSE_FDCIPENDING BIT(21)
-#define ROGUE_MIPSFW_C0_CAUSE_IV BIT(23)
-#define ROGUE_MIPSFW_C0_CAUSE_IC BIT(25)
-#define ROGUE_MIPSFW_C0_CAUSE_PCIPENDING BIT(26)
-#define ROGUE_MIPSFW_C0_CAUSE_TIPENDING BIT(30)
-#define ROGUE_MIPSFW_C0_CAUSE_BRANCH_DELAY BIT(31)
-
-/* Macros to decode C0_Debug register. */
-#define ROGUE_MIPSFW_C0_DEBUG_EXCCODE(debug) (((debug) >> 10) & 0x1f)
-#define ROGUE_MIPSFW_C0_DEBUG_DSS BIT(0)
-#define ROGUE_MIPSFW_C0_DEBUG_DBP BIT(1)
-#define ROGUE_MIPSFW_C0_DEBUG_DDBL BIT(2)
-#define ROGUE_MIPSFW_C0_DEBUG_DDBS BIT(3)
-#define ROGUE_MIPSFW_C0_DEBUG_DIB BIT(4)
-#define ROGUE_MIPSFW_C0_DEBUG_DINT BIT(5)
-#define ROGUE_MIPSFW_C0_DEBUG_DIBIMPR BIT(6)
-#define ROGUE_MIPSFW_C0_DEBUG_DDBLIMPR BIT(18)
-#define ROGUE_MIPSFW_C0_DEBUG_DDBSIMPR BIT(19)
-#define ROGUE_MIPSFW_C0_DEBUG_IEXI BIT(20)
-#define ROGUE_MIPSFW_C0_DEBUG_DBUSEP BIT(21)
-#define ROGUE_MIPSFW_C0_DEBUG_CACHEEP BIT(22)
-#define ROGUE_MIPSFW_C0_DEBUG_MCHECKP BIT(23)
-#define ROGUE_MIPSFW_C0_DEBUG_IBUSEP BIT(24)
-#define ROGUE_MIPSFW_C0_DEBUG_DM BIT(30)
-#define ROGUE_MIPSFW_C0_DEBUG_DBD BIT(31)
-
-/* Macros to decode TLB entries. */
-#define ROGUE_MIPSFW_TLB_GET_MASK(page_mask) (((page_mask) >> 13) & 0XFFFFU)
-/* Page size in KB. */
-#define ROGUE_MIPSFW_TLB_GET_PAGE_SIZE(page_mask) ((((page_mask) | 0x1FFF) + 1) >> 11)
-/* Page size in KB. */
-#define ROGUE_MIPSFW_TLB_GET_PAGE_MASK(page_size) ((((page_size) << 11) - 1) & ~0x7FF)
-#define ROGUE_MIPSFW_TLB_GET_VPN2(entry_hi) ((entry_hi) >> 13)
-#define ROGUE_MIPSFW_TLB_GET_COHERENCY(entry_lo) (((entry_lo) >> 3) & 0x7U)
-#define ROGUE_MIPSFW_TLB_GET_PFN(entry_lo) (((entry_lo) >> 6) & 0XFFFFFU)
-/* GET_PA uses a non-standard PFN mask for 36 bit addresses. */
-#define ROGUE_MIPSFW_TLB_GET_PA(entry_lo) (((u64)(entry_lo) & \
-					    ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT) << 6)
-#define ROGUE_MIPSFW_TLB_GET_INHIBIT(entry_lo) (((entry_lo) >> 30) & 0x3U)
-#define ROGUE_MIPSFW_TLB_GET_DGV(entry_lo) ((entry_lo) & 0x7U)
-#define ROGUE_MIPSFW_TLB_GLOBAL BIT(0)
-#define ROGUE_MIPSFW_TLB_VALID BIT(1)
-#define ROGUE_MIPSFW_TLB_DIRTY BIT(2)
-#define ROGUE_MIPSFW_TLB_XI BIT(30)
-#define ROGUE_MIPSFW_TLB_RI BIT(31)
-
-#define ROGUE_MIPSFW_REMAP_GET_REGION_SIZE(region_size_encoding) (1 << (((region_size_encoding) \
-									+ 1) << 1))
-
-struct rogue_mips_tlb_entry {
-	u32 tlb_page_mask;
-	u32 tlb_hi;
-	u32 tlb_lo0;
-	u32 tlb_lo1;
-};
-
-struct rogue_mips_remap_entry {
-	u32 remap_addr_in;  /* Always 4k aligned. */
-	u32 remap_addr_out; /* Always 4k aligned. */
-	u32 remap_region_size;
-};
-
-struct rogue_mips_state {
-	u32 error_state; /* This must come first in the structure. */
-	u32 error_epc;
-	u32 status_register;
-	u32 cause_register;
-	u32 bad_register;
-	u32 epc;
-	u32 sp;
-	u32 debug;
-	u32 depc;
-	u32 bad_instr;
-	u32 unmapped_address;
-	struct rogue_mips_tlb_entry tlb[ROGUE_MIPSFW_NUMBER_OF_TLB_ENTRIES];
-	struct rogue_mips_remap_entry remap[ROGUE_MIPSFW_NUMBER_OF_REMAP_ENTRIES];
-};
-
-#include "pvr_rogue_mips_internal_check.h"
-
-#endif /* PVR_ROGUE_MIPS_INTERNAL_H */
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
deleted file mode 100644
index 60bc83d7cdbc..000000000000
--- a/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
-/* Copyright (c) 2023 Imagination Technologies Ltd. */
-
-#ifndef PVR_ROGUE_MIPS_INTERNAL_CHECK_H
-#define PVR_ROGUE_MIPS_INTERNAL_CHECK_H
-
-#include "pvr_check.h"
-
-OFFSET_CHECK(struct rogue_mips_tlb_entry, tlb_page_mask, 0);
-OFFSET_CHECK(struct rogue_mips_tlb_entry, tlb_hi, 4);
-OFFSET_CHECK(struct rogue_mips_tlb_entry, tlb_lo0, 8);
-OFFSET_CHECK(struct rogue_mips_tlb_entry, tlb_lo1, 12);
-SIZE_CHECK(struct rogue_mips_tlb_entry, 16);
-
-OFFSET_CHECK(struct rogue_mips_remap_entry, remap_addr_in, 0);
-OFFSET_CHECK(struct rogue_mips_remap_entry, remap_addr_out, 4);
-OFFSET_CHECK(struct rogue_mips_remap_entry, remap_region_size, 8);
-SIZE_CHECK(struct rogue_mips_remap_entry, 12);
-
-OFFSET_CHECK(struct rogue_mips_state, error_state, 0);
-OFFSET_CHECK(struct rogue_mips_state, error_epc, 4);
-OFFSET_CHECK(struct rogue_mips_state, status_register, 8);
-OFFSET_CHECK(struct rogue_mips_state, cause_register, 12);
-OFFSET_CHECK(struct rogue_mips_state, bad_register, 16);
-OFFSET_CHECK(struct rogue_mips_state, epc, 20);
-OFFSET_CHECK(struct rogue_mips_state, sp, 24);
-OFFSET_CHECK(struct rogue_mips_state, debug, 28);
-OFFSET_CHECK(struct rogue_mips_state, depc, 32);
-OFFSET_CHECK(struct rogue_mips_state, bad_instr, 36);
-OFFSET_CHECK(struct rogue_mips_state, unmapped_address, 40);
-OFFSET_CHECK(struct rogue_mips_state, tlb, 44);
-OFFSET_CHECK(struct rogue_mips_state, remap, 300);
-SIZE_CHECK(struct rogue_mips_state, 684);
-
-#endif /* PVR_ROGUE_MIPS_INTERNAL_CHECK_H */
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
index 264ea0fccf9c..84e023fffe5a 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
@@ -3,10 +3,10 @@
 
 #include "pvr_device.h"
 #include "pvr_gem.h"
+#define PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#include "pvr_mips_internal.h"
+#undef PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_mmu.h"
-#define PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
-#include "pvr_rogue_mips_internal.h"
-#undef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_vm.h"
 #include "pvr_vm_mips.h"
 
@@ -18,7 +18,7 @@
 #include <linux/vmalloc.h>
 
 #define PVR_MIPS_PT_PAGE_COUNT \
-	DIV_ROUND_UP(ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
+	DIV_ROUND_UP(PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES * PVR_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
 
 /**
  * struct pvr_vm_mips_data - MIPS-VM-specific data
@@ -55,15 +55,15 @@ struct pvr_vm_mips_data {
 int
 pvr_vm_mips_init(struct pvr_device *pvr_dev)
 {
-	u32 pt_size = 1 << ROGUE_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev);
+	u32 pt_size = 1 << PVR_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev);
 	struct device *dev = from_pvr_device(pvr_dev)->dev;
 	struct pvr_vm_mips_data *vm_data;
 	u32 phys_bus_width;
 	int page_nr;
 	int err;
 
-	/* Page table size must be at most ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * 4k pages. */
-	if (pt_size > ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * SZ_4K)
+	/* Page table size must be at most PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES * 4k pages. */
+	if (pt_size > PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES * SZ_4K)
 		return -EINVAL;
 
 	if (PVR_FEATURE_VALUE(pvr_dev, phys_bus_width, &phys_bus_width))
@@ -96,11 +96,11 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)
 		goto err_free_pages;
 	}
 
-	vm_data->pfn_mask = (phys_bus_width > 32) ? ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
-						    ROGUE_MIPSFW_ENTRYLO_PFN_MASK;
+	vm_data->pfn_mask = (phys_bus_width > 32) ? PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
+						    PVR_MIPSFW_ENTRYLO_PFN_MASK;
 
-	vm_data->cache_policy = (phys_bus_width > 32) ? ROGUE_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
-							ROGUE_MIPSFW_CACHED_POLICY;
+	vm_data->cache_policy = (phys_bus_width > 32) ? PVR_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
+							PVR_MIPSFW_CACHED_POLICY;
 
 	pvr_dev->fw_dev.processor_data.mips_data.vm_data = vm_data;
 
@@ -144,15 +144,15 @@ get_mips_pte_flags(bool read, bool write, u32 cache_policy)
 	u32 flags = 0;
 
 	if (read && write) /* Read/write. */
-		flags |= ROGUE_MIPSFW_ENTRYLO_DIRTY_EN;
+		flags |= PVR_MIPSFW_ENTRYLO_DIRTY_EN;
 	else if (write)    /* Write only. */
-		flags |= ROGUE_MIPSFW_ENTRYLO_READ_INHIBIT_EN;
+		flags |= PVR_MIPSFW_ENTRYLO_READ_INHIBIT_EN;
 	else
 		WARN_ON(!read);
 
-	flags |= cache_policy << ROGUE_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT;
+	flags |= cache_policy << PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT;
 
-	flags |= ROGUE_MIPSFW_ENTRYLO_VALID_EN | ROGUE_MIPSFW_ENTRYLO_GLOBAL_EN;
+	flags |= PVR_MIPSFW_ENTRYLO_VALID_EN | PVR_MIPSFW_ENTRYLO_GLOBAL_EN;
 
 	return flags;
 }
@@ -190,15 +190,15 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 	    start >= ROGUE_FW_HEAP_BASE + fw_dev->fw_heap_info.raw_size ||
 	    end < ROGUE_FW_HEAP_BASE ||
 	    end >= ROGUE_FW_HEAP_BASE + fw_dev->fw_heap_info.raw_size ||
-	    (start & ROGUE_MIPSFW_PAGE_MASK_4K) ||
-	    ((end + 1) & ROGUE_MIPSFW_PAGE_MASK_4K))
+	    (start & PVR_MIPSFW_PAGE_MASK_4K) ||
+	    ((end + 1) & PVR_MIPSFW_PAGE_MASK_4K))
 		return -EINVAL;
 
-	start_pfn = (start & fw_dev->fw_heap_info.offset_mask) >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
-	end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
+	start_pfn = (start & fw_dev->fw_heap_info.offset_mask) >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
+	end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
 
 	if (pvr_obj->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
-		cache_policy = ROGUE_MIPSFW_UNCACHED_CACHE_POLICY;
+		cache_policy = PVR_MIPSFW_UNCACHED_CACHE_POLICY;
 	else
 		cache_policy = vm_data->cache_policy;
 
@@ -210,13 +210,13 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 
 		err = pvr_fw_object_get_dma_addr(fw_obj,
 						 (pfn - start_pfn) <<
-						 ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K,
+						 PVR_MIPSFW_LOG2_PAGE_SIZE_4K,
 						 &dma_addr);
 		if (err)
 			goto err_unmap_pages;
 
-		pte = ((dma_addr >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-		       << ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT) & vm_data->pfn_mask;
+		pte = ((dma_addr >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
+		       << PVR_MIPSFW_ENTRYLO_PFN_SHIFT) & vm_data->pfn_mask;
 		pte |= pte_flags;
 
 		WRITE_ONCE(vm_data->pt[pfn], pte);
@@ -251,9 +251,9 @@ pvr_vm_mips_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 	const u64 end = start + size;
 
 	const u32 start_pfn = (start & fw_dev->fw_heap_info.offset_mask) >>
-			      ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
+			      PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
 	const u32 end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >>
-			    ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
+			    PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
 
 	for (u32 pfn = start_pfn; pfn < end_pfn; pfn++)
 		WRITE_ONCE(vm_data->pt[pfn], 0);
@@ -283,8 +283,8 @@ pvr_vm_get_pt_phys_addrs(struct pvr_device *pvr_dev, u64 *phys_addrs, int max_nu
 
 	for (u32 page_nr = 0; page_nr < max_num_addrs; page_nr++) {
 		/* Firmware expects 4k pages, but host page size might be different. */
-		u32 src_page_nr = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) >> PAGE_SHIFT;
-		u32 page_offset = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) & ~PAGE_MASK;
+		u32 src_page_nr = (page_nr * PVR_MIPSFW_PAGE_SIZE_4K) >> PAGE_SHIFT;
+		u32 page_offset = (page_nr * PVR_MIPSFW_PAGE_SIZE_4K) & ~PAGE_MASK;
 
 		phys_addrs[page_nr] = vm_data->pt_dma_addr[src_page_nr] + page_offset;
 	}

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/4] drm/imagination: Make the MIPS firmware headers arch-independent
@ 2026-10-14  8:13   ` Alexandru Dadu
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu

From: Alessio Belle <alessio.belle@imgtec.com>

While this header is specific to Rogue, rename it and its contents
anyway with arch-independent prefixes for consistency with the other
firmware processor headers.

Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
 drivers/gpu/drm/imagination/pvr_fw_mips.c          |  28 +-
 drivers/gpu/drm/imagination/pvr_mips_internal.h    | 339 +++++++++++++++++++++
 .../gpu/drm/imagination/pvr_mips_internal_check.h  |  35 +++
 .../gpu/drm/imagination/pvr_rogue_mips_internal.h  | 339 ---------------------
 .../imagination/pvr_rogue_mips_internal_check.h    |  35 ---
 drivers/gpu/drm/imagination/pvr_vm_mips.c          |  54 ++--
 6 files changed, 415 insertions(+), 415 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.c b/drivers/gpu/drm/imagination/pvr_fw_mips.c
index 7e4dd23e1f3f..037f5cefe372 100644
--- a/drivers/gpu/drm/imagination/pvr_fw_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_fw_mips.c
@@ -4,9 +4,9 @@
 #include "pvr_device.h"
 #include "pvr_fw.h"
 #include "pvr_gem.h"
-#define PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
-#include "pvr_rogue_mips_internal.h"
-#undef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#define PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#include "pvr_mips_internal.h"
+#undef PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_vm_mips.h"
 
 #include <linux/err.h>
@@ -63,7 +63,7 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 	const struct pvr_fw_layout_entry *boot_data_entry;
 	const struct pvr_fw_layout_entry *exception_code_entry;
 	const struct pvr_fw_layout_entry *stack_entry;
-	struct rogue_mipsfw_boot_data *boot_data;
+	struct pvr_mipsfw_boot_data *boot_data;
 	dma_addr_t dma_addr;
 	int err;
 
@@ -90,8 +90,8 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 	if (!stack_entry)
 		return -EINVAL;
 
-	boot_data = (struct rogue_mipsfw_boot_data *)(fw_data_ptr + boot_data_entry->alloc_offset +
-						      ROGUE_MIPSFW_BOOTLDR_CONF_OFFSET);
+	boot_data = (struct pvr_mipsfw_boot_data *)(fw_data_ptr + boot_data_entry->alloc_offset +
+						    PVR_MIPSFW_BOOTLDR_CONF_OFFSET);
 
 	WARN_ON(pvr_fw_object_get_dma_addr(fw_dev->mem.data_obj, stack_entry->alloc_offset,
 					   &dma_addr));
@@ -104,8 +104,8 @@ pvr_mips_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
 	if (err)
 		return err;
 
-	boot_data->pt_log2_page_size = ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
-	boot_data->pt_num_pages = ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES;
+	boot_data->pt_log2_page_size = PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
+	boot_data->pt_num_pages = PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES;
 	boot_data->reserved1 = 0;
 	boot_data->reserved2 = 0;
 
@@ -116,7 +116,7 @@ static int
 pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 {
 	struct pvr_fw_mips_data *fw_data = pvr_dev->fw_dev.processor_data.mips_data.fw_data;
-	const u64 remap_settings = ROGUE_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE;
+	const u64 remap_settings = PVR_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE;
 	u32 phys_bus_width;
 
 	int err = PVR_FEATURE_VALUE(pvr_dev, phys_bus_width, &phys_bus_width);
@@ -129,13 +129,13 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 		return -EINVAL;
 
 	pvr_cr_write32(pvr_dev, ROGUE_CR_MIPS_WRAPPER_CONFIG,
-		       (ROGUE_MIPSFW_REGISTERS_VIRTUAL_BASE >>
-			ROGUE_MIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN) |
+		       (PVR_MIPSFW_REGISTERS_VIRTUAL_BASE >>
+			PVR_MIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN) |
 		       ROGUE_CR_MIPS_WRAPPER_CONFIG_BOOT_ISA_MODE_MICROMIPS);
 
 	/* Configure remap for boot code, boot data and exceptions code areas. */
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG1,
-		       ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN |
+		       PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP1_CONFIG2,
 		       (fw_data->boot_code_dma_addr &
@@ -157,14 +157,14 @@ pvr_mips_wrapper_init(struct pvr_device *pvr_dev)
 	}
 
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG1,
-		       ROGUE_MIPSFW_DATA_REMAP_PHYS_ADDR_IN |
+		       PVR_MIPSFW_DATA_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2,
 		       (fw_data->boot_data_dma_addr &
 			~ROGUE_CR_MIPS_ADDR_REMAP2_CONFIG2_ADDR_OUT_CLRMSK) | remap_settings);
 
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1,
-		       ROGUE_MIPSFW_CODE_REMAP_PHYS_ADDR_IN |
+		       PVR_MIPSFW_CODE_REMAP_PHYS_ADDR_IN |
 		       ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG1_MODE_ENABLE_EN);
 	pvr_cr_write64(pvr_dev, ROGUE_CR_MIPS_ADDR_REMAP3_CONFIG2,
 		       (fw_data->exception_code_dma_addr &
diff --git a/drivers/gpu/drm/imagination/pvr_mips_internal.h b/drivers/gpu/drm/imagination/pvr_mips_internal.h
new file mode 100644
index 000000000000..732730d64bf5
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_mips_internal.h
@@ -0,0 +1,339 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/* Copyright (c) 2023 Imagination Technologies Ltd. */
+
+#ifndef PVR_MIPS_INTERNAL_H
+#define PVR_MIPS_INTERNAL_H
+
+#ifndef PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#error This file may only be included if explicitly defined
+#endif
+
+#include <linux/bits.h>
+#include <linux/types.h>
+
+/* Utility defines for memory management. */
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_4K (12)
+#define PVR_MIPSFW_PAGE_SIZE_4K (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
+#define PVR_MIPSFW_PAGE_MASK_4K (PVR_MIPSFW_PAGE_SIZE_4K - 1)
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_64K (16)
+#define PVR_MIPSFW_PAGE_SIZE_64K (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_64K)
+#define PVR_MIPSFW_PAGE_MASK_64K (PVR_MIPSFW_PAGE_SIZE_64K - 1)
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_256K (18)
+#define PVR_MIPSFW_PAGE_SIZE_256K (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_256K)
+#define PVR_MIPSFW_PAGE_MASK_256K (PVR_MIPSFW_PAGE_SIZE_256K - 1)
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_1MB (20)
+#define PVR_MIPSFW_PAGE_SIZE_1MB (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_1MB)
+#define PVR_MIPSFW_PAGE_MASK_1MB (PVR_MIPSFW_PAGE_SIZE_1MB - 1)
+#define PVR_MIPSFW_LOG2_PAGE_SIZE_4MB (22)
+#define PVR_MIPSFW_PAGE_SIZE_4MB (0x1 << PVR_MIPSFW_LOG2_PAGE_SIZE_4MB)
+#define PVR_MIPSFW_PAGE_MASK_4MB (PVR_MIPSFW_PAGE_SIZE_4MB - 1)
+#define PVR_MIPSFW_LOG2_PTE_ENTRY_SIZE (2)
+/* log2 page table sizes dependent on FW heap size and page size (for each OS). */
+#define PVR_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev) ((pvr_dev)->fw_dev.fw_heap_info.log2_size - \
+						    PVR_MIPSFW_LOG2_PAGE_SIZE_4K +    \
+						    PVR_MIPSFW_LOG2_PTE_ENTRY_SIZE)
+#define PVR_MIPSFW_LOG2_PAGETABLE_SIZE_64K(pvr_dev) ((pvr_dev)->fw_dev.fw_heap_info.log2_size - \
+						     PVR_MIPSFW_LOG2_PAGE_SIZE_64K +   \
+						     PVR_MIPSFW_LOG2_PTE_ENTRY_SIZE)
+/* Maximum number of page table pages (both Host and MIPS pages). */
+#define PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES (4)
+/* Total number of TLB entries. */
+#define PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES (16)
+/* "Uncached" caching policy. */
+#define PVR_MIPSFW_UNCACHED_CACHE_POLICY (2)
+/* "Write-back write-allocate" caching policy. */
+#define PVR_MIPSFW_WRITEBACK_CACHE_POLICY (3)
+/* "Write-through no write-allocate" caching policy. */
+#define PVR_MIPSFW_WRITETHROUGH_CACHE_POLICY (1)
+/* Cached policy used by MIPS in case of physical bus on 32 bit. */
+#define PVR_MIPSFW_CACHED_POLICY (PVR_MIPSFW_WRITEBACK_CACHE_POLICY)
+/* Cached policy used by MIPS in case of physical bus on more than 32 bit. */
+#define PVR_MIPSFW_CACHED_POLICY_ABOVE_32BIT (PVR_MIPSFW_WRITETHROUGH_CACHE_POLICY)
+/* Total number of Remap entries. */
+#define PVR_MIPSFW_NUMBER_OF_REMAP_ENTRIES (2 * PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES)
+
+/* MIPS EntryLo/PTE format. */
+
+#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_SHIFT (31U)
+#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_CLRMSK (0X7FFFFFFF)
+#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_EN (0X80000000)
+
+#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_SHIFT (30U)
+#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_CLRMSK (0XBFFFFFFF)
+#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_EN (0X40000000)
+
+/* Page Frame Number */
+#define PVR_MIPSFW_ENTRYLO_PFN_SHIFT (6)
+#define PVR_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT (12)
+/* Mask used for the MIPS Page Table in case of physical bus on 32 bit. */
+#define PVR_MIPSFW_ENTRYLO_PFN_MASK (0x03FFFFC0)
+#define PVR_MIPSFW_ENTRYLO_PFN_SIZE (20)
+/* Mask used for the MIPS Page Table in case of physical bus on more than 32 bit. */
+#define PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT (0x3FFFFFC0)
+#define PVR_MIPSFW_ENTRYLO_PFN_SIZE_ABOVE_32BIT (24)
+#define PVR_MIPSFW_ADDR_TO_ENTRYLO_PFN_RSHIFT (PVR_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT - \
+					       PVR_MIPSFW_ENTRYLO_PFN_SHIFT)
+
+#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT (3U)
+#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY_CLRMSK (0XFFFFFFC7)
+
+#define PVR_MIPSFW_ENTRYLO_DIRTY_SHIFT (2U)
+#define PVR_MIPSFW_ENTRYLO_DIRTY_CLRMSK (0XFFFFFFFB)
+#define PVR_MIPSFW_ENTRYLO_DIRTY_EN (0X00000004)
+
+#define PVR_MIPSFW_ENTRYLO_VALID_SHIFT (1U)
+#define PVR_MIPSFW_ENTRYLO_VALID_CLRMSK (0XFFFFFFFD)
+#define PVR_MIPSFW_ENTRYLO_VALID_EN (0X00000002)
+
+#define PVR_MIPSFW_ENTRYLO_GLOBAL_SHIFT (0U)
+#define PVR_MIPSFW_ENTRYLO_GLOBAL_CLRMSK (0XFFFFFFFE)
+#define PVR_MIPSFW_ENTRYLO_GLOBAL_EN (0X00000001)
+
+#define PVR_MIPSFW_ENTRYLO_DVG (PVR_MIPSFW_ENTRYLO_DIRTY_EN | \
+				PVR_MIPSFW_ENTRYLO_VALID_EN | \
+				PVR_MIPSFW_ENTRYLO_GLOBAL_EN)
+#define PVR_MIPSFW_ENTRYLO_UNCACHED (PVR_MIPSFW_UNCACHED_CACHE_POLICY << \
+				     PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT)
+#define PVR_MIPSFW_ENTRYLO_DVG_UNCACHED (PVR_MIPSFW_ENTRYLO_DVG | \
+					 PVR_MIPSFW_ENTRYLO_UNCACHED)
+
+/* Remap Range Config Addr Out. */
+/* These defines refer to the upper half of the Remap Range Config register. */
+#define PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_MASK (0x0FFFFFF0)
+#define PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_SHIFT (4) /* wrt upper half of the register. */
+#define PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_ALIGNSHIFT (12)
+#define PVR_MIPSFW_ADDR_TO_RR_ADDR_OUT_RSHIFT (PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_ALIGNSHIFT - \
+					       PVR_MIPSFW_REMAP_RANGE_ADDR_OUT_SHIFT)
+
+/*
+ * Pages to trampoline problematic physical addresses:
+ *   - PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN : 0x1FC0_0000
+ *   - PVR_MIPSFW_DATA_REMAP_PHYS_ADDR_IN : 0x1FC0_1000
+ *   - PVR_MIPSFW_CODE_REMAP_PHYS_ADDR_IN : 0x1FC0_2000
+ *   - (benign trampoline)               : 0x1FC0_3000
+ * that would otherwise be erroneously remapped by the MIPS wrapper.
+ * (see "Firmware virtual layout and remap configuration" section below)
+ */
+
+#define PVR_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES (2)
+#define PVR_MIPSFW_TRAMPOLINE_NUMPAGES BIT(PVR_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES)
+#define PVR_MIPSFW_TRAMPOLINE_SIZE (PVR_MIPSFW_TRAMPOLINE_NUMPAGES << \
+				    PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
+#define PVR_MIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE (PVR_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES + \
+						 PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
+
+#define PVR_MIPSFW_TRAMPOLINE_TARGET_PHYS_ADDR (PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
+#define PVR_MIPSFW_TRAMPOLINE_OFFSET(a) ((a) - PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
+
+#define PVR_MIPSFW_SENSITIVE_ADDR(a) (PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN == \
+				      (~((1 << PVR_MIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE) - 1) \
+				       & (a)))
+
+/* Firmware virtual layout and remap configuration. */
+/*
+ * For each remap region we define:
+ * - the virtual base used by the Firmware to access code/data through that region
+ * - the microAptivAP physical address correspondent to the virtual base address,
+ *   used as input address and remapped to the actual physical address
+ * - log2 of size of the region remapped by the MIPS wrapper, i.e. number of bits from
+ *   the bottom of the base input address that survive onto the output address
+ *   (this defines both the alignment and the maximum size of the remapped region)
+ * - one or more code/data segments within the remapped region.
+ */
+
+/* Boot remap setup. */
+#define PVR_MIPSFW_BOOT_REMAP_VIRTUAL_BASE (0xBFC00000)
+#define PVR_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN (0x1FC00000)
+#define PVR_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE (12)
+#define PVR_MIPSFW_BOOT_NMI_CODE_VIRTUAL_BASE (PVR_MIPSFW_BOOT_REMAP_VIRTUAL_BASE)
+
+/* Data remap setup. */
+#define PVR_MIPSFW_DATA_REMAP_VIRTUAL_BASE (0xBFC01000)
+#define PVR_MIPSFW_DATA_CACHED_REMAP_VIRTUAL_BASE (0x9FC01000)
+#define PVR_MIPSFW_DATA_REMAP_PHYS_ADDR_IN (0x1FC01000)
+#define PVR_MIPSFW_DATA_REMAP_LOG2_SEGMENT_SIZE (12)
+#define PVR_MIPSFW_BOOT_NMI_DATA_VIRTUAL_BASE (PVR_MIPSFW_DATA_REMAP_VIRTUAL_BASE)
+
+/* Code remap setup. */
+#define PVR_MIPSFW_CODE_REMAP_VIRTUAL_BASE (0x9FC02000)
+#define PVR_MIPSFW_CODE_REMAP_PHYS_ADDR_IN (0x1FC02000)
+#define PVR_MIPSFW_CODE_REMAP_LOG2_SEGMENT_SIZE (12)
+#define PVR_MIPSFW_EXCEPTIONS_VIRTUAL_BASE (PVR_MIPSFW_CODE_REMAP_VIRTUAL_BASE)
+
+/* Permanent mappings setup. */
+#define PVR_MIPSFW_PT_VIRTUAL_BASE (0xCF000000)
+#define PVR_MIPSFW_REGISTERS_VIRTUAL_BASE (0xCF800000)
+#define PVR_MIPSFW_STACK_VIRTUAL_BASE (0xCF600000)
+
+/* Bootloader configuration data. */
+/*
+ * Bootloader configuration offset (where PVR_MIPSFW_BOOT_DATA lives)
+ * within the bootloader/NMI data page.
+ */
+#define PVR_MIPSFW_BOOTLDR_CONF_OFFSET (0x0)
+
+/* NMI shared data. */
+/* Base address of the shared data within the bootloader/NMI data page. */
+#define PVR_MIPSFW_NMI_SHARED_DATA_BASE (0x100)
+/* Size used by Debug dump data. */
+#define PVR_MIPSFW_NMI_SHARED_SIZE (0x2B0)
+/* Offsets in the NMI shared area in 32-bit words. */
+#define PVR_MIPSFW_NMI_SYNC_FLAG_OFFSET (0x0)
+#define PVR_MIPSFW_NMI_STATE_OFFSET (0x1)
+#define PVR_MIPSFW_NMI_ERROR_STATE_SET (0x1)
+
+/* MIPS boot stage. */
+#define PVR_MIPSFW_BOOT_STAGE_OFFSET (0x400)
+
+/*
+ * MIPS private data in the bootloader data page.
+ * Memory below this offset is used by the FW only, no interface data allowed.
+ */
+#define PVR_MIPSFW_PRIVATE_DATA_OFFSET (0x800)
+
+struct pvr_mipsfw_boot_data {
+	u64 stack_phys_addr;
+	u64 reg_base;
+	u64 pt_phys_addr[PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES];
+	u32 pt_log2_page_size;
+	u32 pt_num_pages;
+	u32 reserved1;
+	u32 reserved2;
+};
+
+#define PVR_MIPSFW_GET_OFFSET_IN_DWORDS(offset) ((offset) / sizeof(u32))
+#define PVR_MIPSFW_GET_OFFSET_IN_QWORDS(offset) ((offset) / sizeof(u64))
+
+/* Used for compatibility checks. */
+#define PVR_MIPSFW_ARCHTYPE_VER_CLRMSK (0xFFFFE3FFU)
+#define PVR_MIPSFW_ARCHTYPE_VER_SHIFT (10U)
+#define PVR_MIPSFW_CORE_ID_VALUE (0x001U)
+#define PVR_FW_PROCESSOR_MIPS "MIPS"
+
+/* microAptivAP cache line size. */
+#define PVR_MIPSFW_MICROAPTIVEAP_CACHELINE_SIZE (16U)
+
+/*
+ * The SOCIF transactions are identified with the top 16 bits of the physical address emitted by
+ * the MIPS.
+ */
+#define PVR_MIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN (16U)
+
+/* Values to put in the MIPS selectors for performance counters. */
+/* Icache accesses in COUNTER0. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_ICACHE_ACCESSES_C0 (9U)
+/* Icache misses in COUNTER1. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_ICACHE_MISSES_C1 (9U)
+
+/* Dcache accesses in COUNTER0. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_DCACHE_ACCESSES_C0 (10U)
+/* Dcache misses in COUNTER1. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_DCACHE_MISSES_C1 (11U)
+
+/* ITLB instruction accesses in COUNTER0. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_ITLB_INSTR_ACCESSES_C0 (5U)
+/* JTLB instruction accesses misses in COUNTER1. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_JTLB_INSTR_MISSES_C1 (7U)
+
+  /* Instructions completed in COUNTER0. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_INSTR_COMPLETED_C0 (1U)
+/* JTLB data misses in COUNTER1. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_JTLB_DATA_MISSES_C1 (8U)
+
+/* Shift for the Event field in the MIPS perf ctrl registers. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_EVENT_SHIFT (5U)
+
+/* Additional flags for performance counters. See MIPS manual for further reference. */
+#define PVR_MIPSFW_PERF_COUNT_CTRL_COUNT_USER_MODE (8U)
+#define PVR_MIPSFW_PERF_COUNT_CTRL_COUNT_KERNEL_MODE (2U)
+#define PVR_MIPSFW_PERF_COUNT_CTRL_COUNT_EXL (1U)
+
+#define PVR_MIPSFW_C0_NBHWIRQ	8
+
+/* Macros to decode C0_Cause register. */
+#define PVR_MIPSFW_C0_CAUSE_EXCCODE(cause) (((cause) & 0x7c) >> 2)
+#define PVR_MIPSFW_C0_CAUSE_EXCCODE_FWERROR 9
+/* Use only when Coprocessor Unusable exception. */
+#define PVR_MIPSFW_C0_CAUSE_UNUSABLE_UNIT(cause) (((cause) >> 28) & 0x3)
+#define PVR_MIPSFW_C0_CAUSE_PENDING_HWIRQ(cause) (((cause) & 0x3fc00) >> 10)
+#define PVR_MIPSFW_C0_CAUSE_FDCIPENDING BIT(21)
+#define PVR_MIPSFW_C0_CAUSE_IV BIT(23)
+#define PVR_MIPSFW_C0_CAUSE_IC BIT(25)
+#define PVR_MIPSFW_C0_CAUSE_PCIPENDING BIT(26)
+#define PVR_MIPSFW_C0_CAUSE_TIPENDING BIT(30)
+#define PVR_MIPSFW_C0_CAUSE_BRANCH_DELAY BIT(31)
+
+/* Macros to decode C0_Debug register. */
+#define PVR_MIPSFW_C0_DEBUG_EXCCODE(debug) (((debug) >> 10) & 0x1f)
+#define PVR_MIPSFW_C0_DEBUG_DSS BIT(0)
+#define PVR_MIPSFW_C0_DEBUG_DBP BIT(1)
+#define PVR_MIPSFW_C0_DEBUG_DDBL BIT(2)
+#define PVR_MIPSFW_C0_DEBUG_DDBS BIT(3)
+#define PVR_MIPSFW_C0_DEBUG_DIB BIT(4)
+#define PVR_MIPSFW_C0_DEBUG_DINT BIT(5)
+#define PVR_MIPSFW_C0_DEBUG_DIBIMPR BIT(6)
+#define PVR_MIPSFW_C0_DEBUG_DDBLIMPR BIT(18)
+#define PVR_MIPSFW_C0_DEBUG_DDBSIMPR BIT(19)
+#define PVR_MIPSFW_C0_DEBUG_IEXI BIT(20)
+#define PVR_MIPSFW_C0_DEBUG_DBUSEP BIT(21)
+#define PVR_MIPSFW_C0_DEBUG_CACHEEP BIT(22)
+#define PVR_MIPSFW_C0_DEBUG_MCHECKP BIT(23)
+#define PVR_MIPSFW_C0_DEBUG_IBUSEP BIT(24)
+#define PVR_MIPSFW_C0_DEBUG_DM BIT(30)
+#define PVR_MIPSFW_C0_DEBUG_DBD BIT(31)
+
+/* Macros to decode TLB entries. */
+#define PVR_MIPSFW_TLB_GET_MASK(page_mask) (((page_mask) >> 13) & 0XFFFFU)
+/* Page size in KB. */
+#define PVR_MIPSFW_TLB_GET_PAGE_SIZE(page_mask) ((((page_mask) | 0x1FFF) + 1) >> 11)
+/* Page size in KB. */
+#define PVR_MIPSFW_TLB_GET_PAGE_MASK(page_size) ((((page_size) << 11) - 1) & ~0x7FF)
+#define PVR_MIPSFW_TLB_GET_VPN2(entry_hi) ((entry_hi) >> 13)
+#define PVR_MIPSFW_TLB_GET_COHERENCY(entry_lo) (((entry_lo) >> 3) & 0x7U)
+#define PVR_MIPSFW_TLB_GET_PFN(entry_lo) (((entry_lo) >> 6) & 0XFFFFFU)
+/* GET_PA uses a non-standard PFN mask for 36 bit addresses. */
+#define PVR_MIPSFW_TLB_GET_PA(entry_lo) (((u64)(entry_lo) & \
+					  PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT) << 6)
+#define PVR_MIPSFW_TLB_GET_INHIBIT(entry_lo) (((entry_lo) >> 30) & 0x3U)
+#define PVR_MIPSFW_TLB_GET_DGV(entry_lo) ((entry_lo) & 0x7U)
+#define PVR_MIPSFW_TLB_GLOBAL BIT(0)
+#define PVR_MIPSFW_TLB_VALID BIT(1)
+#define PVR_MIPSFW_TLB_DIRTY BIT(2)
+#define PVR_MIPSFW_TLB_XI BIT(30)
+#define PVR_MIPSFW_TLB_RI BIT(31)
+
+#define PVR_MIPSFW_REMAP_GET_REGION_SIZE(region_size_encoding) (1 << (((region_size_encoding) \
+								      + 1) << 1))
+
+struct pvr_mips_tlb_entry {
+	u32 tlb_page_mask;
+	u32 tlb_hi;
+	u32 tlb_lo0;
+	u32 tlb_lo1;
+};
+
+struct pvr_mips_remap_entry {
+	u32 remap_addr_in;  /* Always 4k aligned. */
+	u32 remap_addr_out; /* Always 4k aligned. */
+	u32 remap_region_size;
+};
+
+struct pvr_mips_state {
+	u32 error_state; /* This must come first in the structure. */
+	u32 error_epc;
+	u32 status_register;
+	u32 cause_register;
+	u32 bad_register;
+	u32 epc;
+	u32 sp;
+	u32 debug;
+	u32 depc;
+	u32 bad_instr;
+	u32 unmapped_address;
+	struct pvr_mips_tlb_entry tlb[PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES];
+	struct pvr_mips_remap_entry remap[PVR_MIPSFW_NUMBER_OF_REMAP_ENTRIES];
+};
+
+#include "pvr_mips_internal_check.h"
+
+#endif /* PVR_MIPS_INTERNAL_H */
diff --git a/drivers/gpu/drm/imagination/pvr_mips_internal_check.h b/drivers/gpu/drm/imagination/pvr_mips_internal_check.h
new file mode 100644
index 000000000000..7583a34bfc72
--- /dev/null
+++ b/drivers/gpu/drm/imagination/pvr_mips_internal_check.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
+/* Copyright (c) 2023 Imagination Technologies Ltd. */
+
+#ifndef PVR_MIPS_INTERNAL_CHECK_H
+#define PVR_MIPS_INTERNAL_CHECK_H
+
+#include "pvr_check.h"
+
+OFFSET_CHECK(struct pvr_mips_tlb_entry, tlb_page_mask, 0);
+OFFSET_CHECK(struct pvr_mips_tlb_entry, tlb_hi, 4);
+OFFSET_CHECK(struct pvr_mips_tlb_entry, tlb_lo0, 8);
+OFFSET_CHECK(struct pvr_mips_tlb_entry, tlb_lo1, 12);
+SIZE_CHECK(struct pvr_mips_tlb_entry, 16);
+
+OFFSET_CHECK(struct pvr_mips_remap_entry, remap_addr_in, 0);
+OFFSET_CHECK(struct pvr_mips_remap_entry, remap_addr_out, 4);
+OFFSET_CHECK(struct pvr_mips_remap_entry, remap_region_size, 8);
+SIZE_CHECK(struct pvr_mips_remap_entry, 12);
+
+OFFSET_CHECK(struct pvr_mips_state, error_state, 0);
+OFFSET_CHECK(struct pvr_mips_state, error_epc, 4);
+OFFSET_CHECK(struct pvr_mips_state, status_register, 8);
+OFFSET_CHECK(struct pvr_mips_state, cause_register, 12);
+OFFSET_CHECK(struct pvr_mips_state, bad_register, 16);
+OFFSET_CHECK(struct pvr_mips_state, epc, 20);
+OFFSET_CHECK(struct pvr_mips_state, sp, 24);
+OFFSET_CHECK(struct pvr_mips_state, debug, 28);
+OFFSET_CHECK(struct pvr_mips_state, depc, 32);
+OFFSET_CHECK(struct pvr_mips_state, bad_instr, 36);
+OFFSET_CHECK(struct pvr_mips_state, unmapped_address, 40);
+OFFSET_CHECK(struct pvr_mips_state, tlb, 44);
+OFFSET_CHECK(struct pvr_mips_state, remap, 300);
+SIZE_CHECK(struct pvr_mips_state, 684);
+
+#endif /* PVR_MIPS_INTERNAL_CHECK_H */
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
deleted file mode 100644
index 68b4db83cb4b..000000000000
--- a/drivers/gpu/drm/imagination/pvr_rogue_mips_internal.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
-/* Copyright (c) 2023 Imagination Technologies Ltd. */
-
-#ifndef PVR_ROGUE_MIPS_INTERNAL_H
-#define PVR_ROGUE_MIPS_INTERNAL_H
-
-#ifndef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
-#error This file may only be included if explicitly defined
-#endif
-
-#include <linux/bits.h>
-#include <linux/types.h>
-
-/* Utility defines for memory management. */
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K (12)
-#define ROGUE_MIPSFW_PAGE_SIZE_4K (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-#define ROGUE_MIPSFW_PAGE_MASK_4K (ROGUE_MIPSFW_PAGE_SIZE_4K - 1)
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_64K (16)
-#define ROGUE_MIPSFW_PAGE_SIZE_64K (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_64K)
-#define ROGUE_MIPSFW_PAGE_MASK_64K (ROGUE_MIPSFW_PAGE_SIZE_64K - 1)
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_256K (18)
-#define ROGUE_MIPSFW_PAGE_SIZE_256K (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_256K)
-#define ROGUE_MIPSFW_PAGE_MASK_256K (ROGUE_MIPSFW_PAGE_SIZE_256K - 1)
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_1MB (20)
-#define ROGUE_MIPSFW_PAGE_SIZE_1MB (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_1MB)
-#define ROGUE_MIPSFW_PAGE_MASK_1MB (ROGUE_MIPSFW_PAGE_SIZE_1MB - 1)
-#define ROGUE_MIPSFW_LOG2_PAGE_SIZE_4MB (22)
-#define ROGUE_MIPSFW_PAGE_SIZE_4MB (0x1 << ROGUE_MIPSFW_LOG2_PAGE_SIZE_4MB)
-#define ROGUE_MIPSFW_PAGE_MASK_4MB (ROGUE_MIPSFW_PAGE_SIZE_4MB - 1)
-#define ROGUE_MIPSFW_LOG2_PTE_ENTRY_SIZE (2)
-/* log2 page table sizes dependent on FW heap size and page size (for each OS). */
-#define ROGUE_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev) ((pvr_dev)->fw_dev.fw_heap_info.log2_size - \
-						      ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K +    \
-						      ROGUE_MIPSFW_LOG2_PTE_ENTRY_SIZE)
-#define ROGUE_MIPSFW_LOG2_PAGETABLE_SIZE_64K(pvr_dev) ((pvr_dev)->fw_dev.fw_heap_info.log2_size - \
-						       ROGUE_MIPSFW_LOG2_PAGE_SIZE_64K +   \
-						       ROGUE_MIPSFW_LOG2_PTE_ENTRY_SIZE)
-/* Maximum number of page table pages (both Host and MIPS pages). */
-#define ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES (4)
-/* Total number of TLB entries. */
-#define ROGUE_MIPSFW_NUMBER_OF_TLB_ENTRIES (16)
-/* "Uncached" caching policy. */
-#define ROGUE_MIPSFW_UNCACHED_CACHE_POLICY (2)
-/* "Write-back write-allocate" caching policy. */
-#define ROGUE_MIPSFW_WRITEBACK_CACHE_POLICY (3)
-/* "Write-through no write-allocate" caching policy. */
-#define ROGUE_MIPSFW_WRITETHROUGH_CACHE_POLICY (1)
-/* Cached policy used by MIPS in case of physical bus on 32 bit. */
-#define ROGUE_MIPSFW_CACHED_POLICY (ROGUE_MIPSFW_WRITEBACK_CACHE_POLICY)
-/* Cached policy used by MIPS in case of physical bus on more than 32 bit. */
-#define ROGUE_MIPSFW_CACHED_POLICY_ABOVE_32BIT (ROGUE_MIPSFW_WRITETHROUGH_CACHE_POLICY)
-/* Total number of Remap entries. */
-#define ROGUE_MIPSFW_NUMBER_OF_REMAP_ENTRIES (2 * ROGUE_MIPSFW_NUMBER_OF_TLB_ENTRIES)
-
-/* MIPS EntryLo/PTE format. */
-
-#define ROGUE_MIPSFW_ENTRYLO_READ_INHIBIT_SHIFT (31U)
-#define ROGUE_MIPSFW_ENTRYLO_READ_INHIBIT_CLRMSK (0X7FFFFFFF)
-#define ROGUE_MIPSFW_ENTRYLO_READ_INHIBIT_EN (0X80000000)
-
-#define ROGUE_MIPSFW_ENTRYLO_EXEC_INHIBIT_SHIFT (30U)
-#define ROGUE_MIPSFW_ENTRYLO_EXEC_INHIBIT_CLRMSK (0XBFFFFFFF)
-#define ROGUE_MIPSFW_ENTRYLO_EXEC_INHIBIT_EN (0X40000000)
-
-/* Page Frame Number */
-#define ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT (6)
-#define ROGUE_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT (12)
-/* Mask used for the MIPS Page Table in case of physical bus on 32 bit. */
-#define ROGUE_MIPSFW_ENTRYLO_PFN_MASK (0x03FFFFC0)
-#define ROGUE_MIPSFW_ENTRYLO_PFN_SIZE (20)
-/* Mask used for the MIPS Page Table in case of physical bus on more than 32 bit. */
-#define ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT (0x3FFFFFC0)
-#define ROGUE_MIPSFW_ENTRYLO_PFN_SIZE_ABOVE_32BIT (24)
-#define ROGUE_MIPSFW_ADDR_TO_ENTRYLO_PFN_RSHIFT (ROGUE_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT - \
-						 ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT)
-
-#define ROGUE_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT (3U)
-#define ROGUE_MIPSFW_ENTRYLO_CACHE_POLICY_CLRMSK (0XFFFFFFC7)
-
-#define ROGUE_MIPSFW_ENTRYLO_DIRTY_SHIFT (2U)
-#define ROGUE_MIPSFW_ENTRYLO_DIRTY_CLRMSK (0XFFFFFFFB)
-#define ROGUE_MIPSFW_ENTRYLO_DIRTY_EN (0X00000004)
-
-#define ROGUE_MIPSFW_ENTRYLO_VALID_SHIFT (1U)
-#define ROGUE_MIPSFW_ENTRYLO_VALID_CLRMSK (0XFFFFFFFD)
-#define ROGUE_MIPSFW_ENTRYLO_VALID_EN (0X00000002)
-
-#define ROGUE_MIPSFW_ENTRYLO_GLOBAL_SHIFT (0U)
-#define ROGUE_MIPSFW_ENTRYLO_GLOBAL_CLRMSK (0XFFFFFFFE)
-#define ROGUE_MIPSFW_ENTRYLO_GLOBAL_EN (0X00000001)
-
-#define ROGUE_MIPSFW_ENTRYLO_DVG (ROGUE_MIPSFW_ENTRYLO_DIRTY_EN | \
-				  ROGUE_MIPSFW_ENTRYLO_VALID_EN | \
-				  ROGUE_MIPSFW_ENTRYLO_GLOBAL_EN)
-#define ROGUE_MIPSFW_ENTRYLO_UNCACHED (ROGUE_MIPSFW_UNCACHED_CACHE_POLICY << \
-				       ROGUE_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT)
-#define ROGUE_MIPSFW_ENTRYLO_DVG_UNCACHED (ROGUE_MIPSFW_ENTRYLO_DVG | \
-					   ROGUE_MIPSFW_ENTRYLO_UNCACHED)
-
-/* Remap Range Config Addr Out. */
-/* These defines refer to the upper half of the Remap Range Config register. */
-#define ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_MASK (0x0FFFFFF0)
-#define ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_SHIFT (4) /* wrt upper half of the register. */
-#define ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_ALIGNSHIFT (12)
-#define ROGUE_MIPSFW_ADDR_TO_RR_ADDR_OUT_RSHIFT (ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_ALIGNSHIFT - \
-						 ROGUE_MIPSFW_REMAP_RANGE_ADDR_OUT_SHIFT)
-
-/*
- * Pages to trampoline problematic physical addresses:
- *   - ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN : 0x1FC0_0000
- *   - ROGUE_MIPSFW_DATA_REMAP_PHYS_ADDR_IN : 0x1FC0_1000
- *   - ROGUE_MIPSFW_CODE_REMAP_PHYS_ADDR_IN : 0x1FC0_2000
- *   - (benign trampoline)               : 0x1FC0_3000
- * that would otherwise be erroneously remapped by the MIPS wrapper.
- * (see "Firmware virtual layout and remap configuration" section below)
- */
-
-#define ROGUE_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES (2)
-#define ROGUE_MIPSFW_TRAMPOLINE_NUMPAGES BIT(ROGUE_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES)
-#define ROGUE_MIPSFW_TRAMPOLINE_SIZE (ROGUE_MIPSFW_TRAMPOLINE_NUMPAGES << \
-				      ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-#define ROGUE_MIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE (ROGUE_MIPSFW_TRAMPOLINE_LOG2_NUMPAGES + \
-						   ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-
-#define ROGUE_MIPSFW_TRAMPOLINE_TARGET_PHYS_ADDR (ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
-#define ROGUE_MIPSFW_TRAMPOLINE_OFFSET(a) ((a) - ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
-
-#define ROGUE_MIPSFW_SENSITIVE_ADDR(a) (ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN == \
-					(~((1 << ROGUE_MIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE) - 1) \
-					 & (a)))
-
-/* Firmware virtual layout and remap configuration. */
-/*
- * For each remap region we define:
- * - the virtual base used by the Firmware to access code/data through that region
- * - the microAptivAP physical address correspondent to the virtual base address,
- *   used as input address and remapped to the actual physical address
- * - log2 of size of the region remapped by the MIPS wrapper, i.e. number of bits from
- *   the bottom of the base input address that survive onto the output address
- *   (this defines both the alignment and the maximum size of the remapped region)
- * - one or more code/data segments within the remapped region.
- */
-
-/* Boot remap setup. */
-#define ROGUE_MIPSFW_BOOT_REMAP_VIRTUAL_BASE (0xBFC00000)
-#define ROGUE_MIPSFW_BOOT_REMAP_PHYS_ADDR_IN (0x1FC00000)
-#define ROGUE_MIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE (12)
-#define ROGUE_MIPSFW_BOOT_NMI_CODE_VIRTUAL_BASE (ROGUE_MIPSFW_BOOT_REMAP_VIRTUAL_BASE)
-
-/* Data remap setup. */
-#define ROGUE_MIPSFW_DATA_REMAP_VIRTUAL_BASE (0xBFC01000)
-#define ROGUE_MIPSFW_DATA_CACHED_REMAP_VIRTUAL_BASE (0x9FC01000)
-#define ROGUE_MIPSFW_DATA_REMAP_PHYS_ADDR_IN (0x1FC01000)
-#define ROGUE_MIPSFW_DATA_REMAP_LOG2_SEGMENT_SIZE (12)
-#define ROGUE_MIPSFW_BOOT_NMI_DATA_VIRTUAL_BASE (ROGUE_MIPSFW_DATA_REMAP_VIRTUAL_BASE)
-
-/* Code remap setup. */
-#define ROGUE_MIPSFW_CODE_REMAP_VIRTUAL_BASE (0x9FC02000)
-#define ROGUE_MIPSFW_CODE_REMAP_PHYS_ADDR_IN (0x1FC02000)
-#define ROGUE_MIPSFW_CODE_REMAP_LOG2_SEGMENT_SIZE (12)
-#define ROGUE_MIPSFW_EXCEPTIONS_VIRTUAL_BASE (ROGUE_MIPSFW_CODE_REMAP_VIRTUAL_BASE)
-
-/* Permanent mappings setup. */
-#define ROGUE_MIPSFW_PT_VIRTUAL_BASE (0xCF000000)
-#define ROGUE_MIPSFW_REGISTERS_VIRTUAL_BASE (0xCF800000)
-#define ROGUE_MIPSFW_STACK_VIRTUAL_BASE (0xCF600000)
-
-/* Bootloader configuration data. */
-/*
- * Bootloader configuration offset (where ROGUE_MIPSFW_BOOT_DATA lives)
- * within the bootloader/NMI data page.
- */
-#define ROGUE_MIPSFW_BOOTLDR_CONF_OFFSET (0x0)
-
-/* NMI shared data. */
-/* Base address of the shared data within the bootloader/NMI data page. */
-#define ROGUE_MIPSFW_NMI_SHARED_DATA_BASE (0x100)
-/* Size used by Debug dump data. */
-#define ROGUE_MIPSFW_NMI_SHARED_SIZE (0x2B0)
-/* Offsets in the NMI shared area in 32-bit words. */
-#define ROGUE_MIPSFW_NMI_SYNC_FLAG_OFFSET (0x0)
-#define ROGUE_MIPSFW_NMI_STATE_OFFSET (0x1)
-#define ROGUE_MIPSFW_NMI_ERROR_STATE_SET (0x1)
-
-/* MIPS boot stage. */
-#define ROGUE_MIPSFW_BOOT_STAGE_OFFSET (0x400)
-
-/*
- * MIPS private data in the bootloader data page.
- * Memory below this offset is used by the FW only, no interface data allowed.
- */
-#define ROGUE_MIPSFW_PRIVATE_DATA_OFFSET (0x800)
-
-struct rogue_mipsfw_boot_data {
-	u64 stack_phys_addr;
-	u64 reg_base;
-	u64 pt_phys_addr[ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES];
-	u32 pt_log2_page_size;
-	u32 pt_num_pages;
-	u32 reserved1;
-	u32 reserved2;
-};
-
-#define ROGUE_MIPSFW_GET_OFFSET_IN_DWORDS(offset) ((offset) / sizeof(u32))
-#define ROGUE_MIPSFW_GET_OFFSET_IN_QWORDS(offset) ((offset) / sizeof(u64))
-
-/* Used for compatibility checks. */
-#define ROGUE_MIPSFW_ARCHTYPE_VER_CLRMSK (0xFFFFE3FFU)
-#define ROGUE_MIPSFW_ARCHTYPE_VER_SHIFT (10U)
-#define ROGUE_MIPSFW_CORE_ID_VALUE (0x001U)
-#define ROGUE_FW_PROCESSOR_MIPS "MIPS"
-
-/* microAptivAP cache line size. */
-#define ROGUE_MIPSFW_MICROAPTIVEAP_CACHELINE_SIZE (16U)
-
-/*
- * The SOCIF transactions are identified with the top 16 bits of the physical address emitted by
- * the MIPS.
- */
-#define ROGUE_MIPSFW_WRAPPER_CONFIG_REGBANK_ADDR_ALIGN (16U)
-
-/* Values to put in the MIPS selectors for performance counters. */
-/* Icache accesses in COUNTER0. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_ICACHE_ACCESSES_C0 (9U)
-/* Icache misses in COUNTER1. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_ICACHE_MISSES_C1 (9U)
-
-/* Dcache accesses in COUNTER0. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_DCACHE_ACCESSES_C0 (10U)
-/* Dcache misses in COUNTER1. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_DCACHE_MISSES_C1 (11U)
-
-/* ITLB instruction accesses in COUNTER0. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_ITLB_INSTR_ACCESSES_C0 (5U)
-/* JTLB instruction accesses misses in COUNTER1. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_JTLB_INSTR_MISSES_C1 (7U)
-
-  /* Instructions completed in COUNTER0. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_INSTR_COMPLETED_C0 (1U)
-/* JTLB data misses in COUNTER1. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_JTLB_DATA_MISSES_C1 (8U)
-
-/* Shift for the Event field in the MIPS perf ctrl registers. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_EVENT_SHIFT (5U)
-
-/* Additional flags for performance counters. See MIPS manual for further reference. */
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_COUNT_USER_MODE (8U)
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_COUNT_KERNEL_MODE (2U)
-#define ROGUE_MIPSFW_PERF_COUNT_CTRL_COUNT_EXL (1U)
-
-#define ROGUE_MIPSFW_C0_NBHWIRQ	8
-
-/* Macros to decode C0_Cause register. */
-#define ROGUE_MIPSFW_C0_CAUSE_EXCCODE(cause) (((cause) & 0x7c) >> 2)
-#define ROGUE_MIPSFW_C0_CAUSE_EXCCODE_FWERROR 9
-/* Use only when Coprocessor Unusable exception. */
-#define ROGUE_MIPSFW_C0_CAUSE_UNUSABLE_UNIT(cause) (((cause) >> 28) & 0x3)
-#define ROGUE_MIPSFW_C0_CAUSE_PENDING_HWIRQ(cause) (((cause) & 0x3fc00) >> 10)
-#define ROGUE_MIPSFW_C0_CAUSE_FDCIPENDING BIT(21)
-#define ROGUE_MIPSFW_C0_CAUSE_IV BIT(23)
-#define ROGUE_MIPSFW_C0_CAUSE_IC BIT(25)
-#define ROGUE_MIPSFW_C0_CAUSE_PCIPENDING BIT(26)
-#define ROGUE_MIPSFW_C0_CAUSE_TIPENDING BIT(30)
-#define ROGUE_MIPSFW_C0_CAUSE_BRANCH_DELAY BIT(31)
-
-/* Macros to decode C0_Debug register. */
-#define ROGUE_MIPSFW_C0_DEBUG_EXCCODE(debug) (((debug) >> 10) & 0x1f)
-#define ROGUE_MIPSFW_C0_DEBUG_DSS BIT(0)
-#define ROGUE_MIPSFW_C0_DEBUG_DBP BIT(1)
-#define ROGUE_MIPSFW_C0_DEBUG_DDBL BIT(2)
-#define ROGUE_MIPSFW_C0_DEBUG_DDBS BIT(3)
-#define ROGUE_MIPSFW_C0_DEBUG_DIB BIT(4)
-#define ROGUE_MIPSFW_C0_DEBUG_DINT BIT(5)
-#define ROGUE_MIPSFW_C0_DEBUG_DIBIMPR BIT(6)
-#define ROGUE_MIPSFW_C0_DEBUG_DDBLIMPR BIT(18)
-#define ROGUE_MIPSFW_C0_DEBUG_DDBSIMPR BIT(19)
-#define ROGUE_MIPSFW_C0_DEBUG_IEXI BIT(20)
-#define ROGUE_MIPSFW_C0_DEBUG_DBUSEP BIT(21)
-#define ROGUE_MIPSFW_C0_DEBUG_CACHEEP BIT(22)
-#define ROGUE_MIPSFW_C0_DEBUG_MCHECKP BIT(23)
-#define ROGUE_MIPSFW_C0_DEBUG_IBUSEP BIT(24)
-#define ROGUE_MIPSFW_C0_DEBUG_DM BIT(30)
-#define ROGUE_MIPSFW_C0_DEBUG_DBD BIT(31)
-
-/* Macros to decode TLB entries. */
-#define ROGUE_MIPSFW_TLB_GET_MASK(page_mask) (((page_mask) >> 13) & 0XFFFFU)
-/* Page size in KB. */
-#define ROGUE_MIPSFW_TLB_GET_PAGE_SIZE(page_mask) ((((page_mask) | 0x1FFF) + 1) >> 11)
-/* Page size in KB. */
-#define ROGUE_MIPSFW_TLB_GET_PAGE_MASK(page_size) ((((page_size) << 11) - 1) & ~0x7FF)
-#define ROGUE_MIPSFW_TLB_GET_VPN2(entry_hi) ((entry_hi) >> 13)
-#define ROGUE_MIPSFW_TLB_GET_COHERENCY(entry_lo) (((entry_lo) >> 3) & 0x7U)
-#define ROGUE_MIPSFW_TLB_GET_PFN(entry_lo) (((entry_lo) >> 6) & 0XFFFFFU)
-/* GET_PA uses a non-standard PFN mask for 36 bit addresses. */
-#define ROGUE_MIPSFW_TLB_GET_PA(entry_lo) (((u64)(entry_lo) & \
-					    ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT) << 6)
-#define ROGUE_MIPSFW_TLB_GET_INHIBIT(entry_lo) (((entry_lo) >> 30) & 0x3U)
-#define ROGUE_MIPSFW_TLB_GET_DGV(entry_lo) ((entry_lo) & 0x7U)
-#define ROGUE_MIPSFW_TLB_GLOBAL BIT(0)
-#define ROGUE_MIPSFW_TLB_VALID BIT(1)
-#define ROGUE_MIPSFW_TLB_DIRTY BIT(2)
-#define ROGUE_MIPSFW_TLB_XI BIT(30)
-#define ROGUE_MIPSFW_TLB_RI BIT(31)
-
-#define ROGUE_MIPSFW_REMAP_GET_REGION_SIZE(region_size_encoding) (1 << (((region_size_encoding) \
-									+ 1) << 1))
-
-struct rogue_mips_tlb_entry {
-	u32 tlb_page_mask;
-	u32 tlb_hi;
-	u32 tlb_lo0;
-	u32 tlb_lo1;
-};
-
-struct rogue_mips_remap_entry {
-	u32 remap_addr_in;  /* Always 4k aligned. */
-	u32 remap_addr_out; /* Always 4k aligned. */
-	u32 remap_region_size;
-};
-
-struct rogue_mips_state {
-	u32 error_state; /* This must come first in the structure. */
-	u32 error_epc;
-	u32 status_register;
-	u32 cause_register;
-	u32 bad_register;
-	u32 epc;
-	u32 sp;
-	u32 debug;
-	u32 depc;
-	u32 bad_instr;
-	u32 unmapped_address;
-	struct rogue_mips_tlb_entry tlb[ROGUE_MIPSFW_NUMBER_OF_TLB_ENTRIES];
-	struct rogue_mips_remap_entry remap[ROGUE_MIPSFW_NUMBER_OF_REMAP_ENTRIES];
-};
-
-#include "pvr_rogue_mips_internal_check.h"
-
-#endif /* PVR_ROGUE_MIPS_INTERNAL_H */
diff --git a/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h b/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
deleted file mode 100644
index 60bc83d7cdbc..000000000000
--- a/drivers/gpu/drm/imagination/pvr_rogue_mips_internal_check.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
-/* Copyright (c) 2023 Imagination Technologies Ltd. */
-
-#ifndef PVR_ROGUE_MIPS_INTERNAL_CHECK_H
-#define PVR_ROGUE_MIPS_INTERNAL_CHECK_H
-
-#include "pvr_check.h"
-
-OFFSET_CHECK(struct rogue_mips_tlb_entry, tlb_page_mask, 0);
-OFFSET_CHECK(struct rogue_mips_tlb_entry, tlb_hi, 4);
-OFFSET_CHECK(struct rogue_mips_tlb_entry, tlb_lo0, 8);
-OFFSET_CHECK(struct rogue_mips_tlb_entry, tlb_lo1, 12);
-SIZE_CHECK(struct rogue_mips_tlb_entry, 16);
-
-OFFSET_CHECK(struct rogue_mips_remap_entry, remap_addr_in, 0);
-OFFSET_CHECK(struct rogue_mips_remap_entry, remap_addr_out, 4);
-OFFSET_CHECK(struct rogue_mips_remap_entry, remap_region_size, 8);
-SIZE_CHECK(struct rogue_mips_remap_entry, 12);
-
-OFFSET_CHECK(struct rogue_mips_state, error_state, 0);
-OFFSET_CHECK(struct rogue_mips_state, error_epc, 4);
-OFFSET_CHECK(struct rogue_mips_state, status_register, 8);
-OFFSET_CHECK(struct rogue_mips_state, cause_register, 12);
-OFFSET_CHECK(struct rogue_mips_state, bad_register, 16);
-OFFSET_CHECK(struct rogue_mips_state, epc, 20);
-OFFSET_CHECK(struct rogue_mips_state, sp, 24);
-OFFSET_CHECK(struct rogue_mips_state, debug, 28);
-OFFSET_CHECK(struct rogue_mips_state, depc, 32);
-OFFSET_CHECK(struct rogue_mips_state, bad_instr, 36);
-OFFSET_CHECK(struct rogue_mips_state, unmapped_address, 40);
-OFFSET_CHECK(struct rogue_mips_state, tlb, 44);
-OFFSET_CHECK(struct rogue_mips_state, remap, 300);
-SIZE_CHECK(struct rogue_mips_state, 684);
-
-#endif /* PVR_ROGUE_MIPS_INTERNAL_CHECK_H */
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
index 264ea0fccf9c..84e023fffe5a 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
@@ -3,10 +3,10 @@
 
 #include "pvr_device.h"
 #include "pvr_gem.h"
+#define PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
+#include "pvr_mips_internal.h"
+#undef PVR_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_mmu.h"
-#define PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
-#include "pvr_rogue_mips_internal.h"
-#undef PVR_ROGUE_MIPS_INTERNAL_H_EXPLICIT_INCLUDE
 #include "pvr_vm.h"
 #include "pvr_vm_mips.h"
 
@@ -18,7 +18,7 @@
 #include <linux/vmalloc.h>
 
 #define PVR_MIPS_PT_PAGE_COUNT \
-	DIV_ROUND_UP(ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
+	DIV_ROUND_UP(PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES * PVR_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
 
 /**
  * struct pvr_vm_mips_data - MIPS-VM-specific data
@@ -55,15 +55,15 @@ struct pvr_vm_mips_data {
 int
 pvr_vm_mips_init(struct pvr_device *pvr_dev)
 {
-	u32 pt_size = 1 << ROGUE_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev);
+	u32 pt_size = 1 << PVR_MIPSFW_LOG2_PAGETABLE_SIZE_4K(pvr_dev);
 	struct device *dev = from_pvr_device(pvr_dev)->dev;
 	struct pvr_vm_mips_data *vm_data;
 	u32 phys_bus_width;
 	int page_nr;
 	int err;
 
-	/* Page table size must be at most ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * 4k pages. */
-	if (pt_size > ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * SZ_4K)
+	/* Page table size must be at most PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES * 4k pages. */
+	if (pt_size > PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES * SZ_4K)
 		return -EINVAL;
 
 	if (PVR_FEATURE_VALUE(pvr_dev, phys_bus_width, &phys_bus_width))
@@ -96,11 +96,11 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)
 		goto err_free_pages;
 	}
 
-	vm_data->pfn_mask = (phys_bus_width > 32) ? ROGUE_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
-						    ROGUE_MIPSFW_ENTRYLO_PFN_MASK;
+	vm_data->pfn_mask = (phys_bus_width > 32) ? PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
+						    PVR_MIPSFW_ENTRYLO_PFN_MASK;
 
-	vm_data->cache_policy = (phys_bus_width > 32) ? ROGUE_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
-							ROGUE_MIPSFW_CACHED_POLICY;
+	vm_data->cache_policy = (phys_bus_width > 32) ? PVR_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
+							PVR_MIPSFW_CACHED_POLICY;
 
 	pvr_dev->fw_dev.processor_data.mips_data.vm_data = vm_data;
 
@@ -144,15 +144,15 @@ get_mips_pte_flags(bool read, bool write, u32 cache_policy)
 	u32 flags = 0;
 
 	if (read && write) /* Read/write. */
-		flags |= ROGUE_MIPSFW_ENTRYLO_DIRTY_EN;
+		flags |= PVR_MIPSFW_ENTRYLO_DIRTY_EN;
 	else if (write)    /* Write only. */
-		flags |= ROGUE_MIPSFW_ENTRYLO_READ_INHIBIT_EN;
+		flags |= PVR_MIPSFW_ENTRYLO_READ_INHIBIT_EN;
 	else
 		WARN_ON(!read);
 
-	flags |= cache_policy << ROGUE_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT;
+	flags |= cache_policy << PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT;
 
-	flags |= ROGUE_MIPSFW_ENTRYLO_VALID_EN | ROGUE_MIPSFW_ENTRYLO_GLOBAL_EN;
+	flags |= PVR_MIPSFW_ENTRYLO_VALID_EN | PVR_MIPSFW_ENTRYLO_GLOBAL_EN;
 
 	return flags;
 }
@@ -190,15 +190,15 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 	    start >= ROGUE_FW_HEAP_BASE + fw_dev->fw_heap_info.raw_size ||
 	    end < ROGUE_FW_HEAP_BASE ||
 	    end >= ROGUE_FW_HEAP_BASE + fw_dev->fw_heap_info.raw_size ||
-	    (start & ROGUE_MIPSFW_PAGE_MASK_4K) ||
-	    ((end + 1) & ROGUE_MIPSFW_PAGE_MASK_4K))
+	    (start & PVR_MIPSFW_PAGE_MASK_4K) ||
+	    ((end + 1) & PVR_MIPSFW_PAGE_MASK_4K))
 		return -EINVAL;
 
-	start_pfn = (start & fw_dev->fw_heap_info.offset_mask) >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
-	end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
+	start_pfn = (start & fw_dev->fw_heap_info.offset_mask) >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
+	end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
 
 	if (pvr_obj->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
-		cache_policy = ROGUE_MIPSFW_UNCACHED_CACHE_POLICY;
+		cache_policy = PVR_MIPSFW_UNCACHED_CACHE_POLICY;
 	else
 		cache_policy = vm_data->cache_policy;
 
@@ -210,13 +210,13 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 
 		err = pvr_fw_object_get_dma_addr(fw_obj,
 						 (pfn - start_pfn) <<
-						 ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K,
+						 PVR_MIPSFW_LOG2_PAGE_SIZE_4K,
 						 &dma_addr);
 		if (err)
 			goto err_unmap_pages;
 
-		pte = ((dma_addr >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
-		       << ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT) & vm_data->pfn_mask;
+		pte = ((dma_addr >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
+		       << PVR_MIPSFW_ENTRYLO_PFN_SHIFT) & vm_data->pfn_mask;
 		pte |= pte_flags;
 
 		WRITE_ONCE(vm_data->pt[pfn], pte);
@@ -251,9 +251,9 @@ pvr_vm_mips_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 	const u64 end = start + size;
 
 	const u32 start_pfn = (start & fw_dev->fw_heap_info.offset_mask) >>
-			      ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
+			      PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
 	const u32 end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >>
-			    ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K;
+			    PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
 
 	for (u32 pfn = start_pfn; pfn < end_pfn; pfn++)
 		WRITE_ONCE(vm_data->pt[pfn], 0);
@@ -283,8 +283,8 @@ pvr_vm_get_pt_phys_addrs(struct pvr_device *pvr_dev, u64 *phys_addrs, int max_nu
 
 	for (u32 page_nr = 0; page_nr < max_num_addrs; page_nr++) {
 		/* Firmware expects 4k pages, but host page size might be different. */
-		u32 src_page_nr = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) >> PAGE_SHIFT;
-		u32 page_offset = (page_nr * ROGUE_MIPSFW_PAGE_SIZE_4K) & ~PAGE_MASK;
+		u32 src_page_nr = (page_nr * PVR_MIPSFW_PAGE_SIZE_4K) >> PAGE_SHIFT;
+		u32 page_offset = (page_nr * PVR_MIPSFW_PAGE_SIZE_4K) & ~PAGE_MASK;
 
 		phys_addrs[page_nr] = vm_data->pt_dma_addr[src_page_nr] + page_offset;
 	}

-- 
2.43.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/4] drm/imagination: Improve some logging in error paths
  2026-10-14  8:13 ` Alexandru Dadu
@ 2026-10-14  8:13   ` Alexandru Dadu
  -1 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu,
	Matt Coster

From: Matt Coster <matt.coster@imgtec.com>

Add error messages for attempts to map an already mapped firmware
object, unmap an already unmapped firmware object, and provide too few
DMA address slots for the firmware page table.

Signed-off-by: Matt Coster <matt.coster@imgtec.com>
Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
 drivers/gpu/drm/imagination/pvr_fw.c      | 6 ++++--
 drivers/gpu/drm/imagination/pvr_vm_mips.c | 7 ++++++-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index c6c77b152342..4f2b5c4df600 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -1165,8 +1165,9 @@ pvr_fw_object_fw_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj, u
 	spin_lock(&fw_dev->fw_mm_lock);
 
 	if (drm_mm_node_allocated(&fw_obj->fw_mm_node)) {
-		err = -EINVAL;
-		goto err_unlock;
+		spin_unlock(&fw_dev->fw_mm_lock);
+		drm_err(from_pvr_device(pvr_dev), "FW object is already mapped!\n");
+		return -EINVAL;
 	}
 
 	if (!dev_addr) {
@@ -1232,6 +1233,7 @@ pvr_fw_object_fw_unmap(struct pvr_fw_object *fw_obj)
 
 	if (!drm_mm_node_allocated(&fw_obj->fw_mm_node)) {
 		spin_unlock(&fw_dev->fw_mm_lock);
+		drm_err(from_pvr_device(pvr_dev), "FW object is already unmapped!\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
index 84e023fffe5a..40495b1486a2 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
@@ -11,6 +11,7 @@
 #include "pvr_vm_mips.h"
 
 #include <drm/drm_managed.h>
+#include <drm/drm_print.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -278,8 +279,12 @@ pvr_vm_get_pt_phys_addrs(struct pvr_device *pvr_dev, u64 *phys_addrs, int max_nu
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
 	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
 
-	if (ARRAY_SIZE(vm_data->pt_pages) > max_num_addrs)
+	if (ARRAY_SIZE(vm_data->pt_pages) > max_num_addrs) {
+		drm_err(from_pvr_device(pvr_dev),
+			"Minimum %zu pages required for FW PT, but only %d DMA address slots were provided\n",
+			ARRAY_SIZE(vm_data->pt_pages), max_num_addrs);
 		return -EINVAL;
+	}
 
 	for (u32 page_nr = 0; page_nr < max_num_addrs; page_nr++) {
 		/* Firmware expects 4k pages, but host page size might be different. */

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/4] drm/imagination: Improve some logging in error paths
@ 2026-10-14  8:13   ` Alexandru Dadu
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu,
	Matt Coster

From: Matt Coster <matt.coster@imgtec.com>

Add error messages for attempts to map an already mapped firmware
object, unmap an already unmapped firmware object, and provide too few
DMA address slots for the firmware page table.

Signed-off-by: Matt Coster <matt.coster@imgtec.com>
Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
 drivers/gpu/drm/imagination/pvr_fw.c      | 6 ++++--
 drivers/gpu/drm/imagination/pvr_vm_mips.c | 7 ++++++-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_fw.c b/drivers/gpu/drm/imagination/pvr_fw.c
index c6c77b152342..4f2b5c4df600 100644
--- a/drivers/gpu/drm/imagination/pvr_fw.c
+++ b/drivers/gpu/drm/imagination/pvr_fw.c
@@ -1165,8 +1165,9 @@ pvr_fw_object_fw_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj, u
 	spin_lock(&fw_dev->fw_mm_lock);
 
 	if (drm_mm_node_allocated(&fw_obj->fw_mm_node)) {
-		err = -EINVAL;
-		goto err_unlock;
+		spin_unlock(&fw_dev->fw_mm_lock);
+		drm_err(from_pvr_device(pvr_dev), "FW object is already mapped!\n");
+		return -EINVAL;
 	}
 
 	if (!dev_addr) {
@@ -1232,6 +1233,7 @@ pvr_fw_object_fw_unmap(struct pvr_fw_object *fw_obj)
 
 	if (!drm_mm_node_allocated(&fw_obj->fw_mm_node)) {
 		spin_unlock(&fw_dev->fw_mm_lock);
+		drm_err(from_pvr_device(pvr_dev), "FW object is already unmapped!\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
index 84e023fffe5a..40495b1486a2 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
@@ -11,6 +11,7 @@
 #include "pvr_vm_mips.h"
 
 #include <drm/drm_managed.h>
+#include <drm/drm_print.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -278,8 +279,12 @@ pvr_vm_get_pt_phys_addrs(struct pvr_device *pvr_dev, u64 *phys_addrs, int max_nu
 	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
 	struct pvr_vm_mips_data *vm_data = fw_dev->processor_data.mips_data.vm_data;
 
-	if (ARRAY_SIZE(vm_data->pt_pages) > max_num_addrs)
+	if (ARRAY_SIZE(vm_data->pt_pages) > max_num_addrs) {
+		drm_err(from_pvr_device(pvr_dev),
+			"Minimum %zu pages required for FW PT, but only %d DMA address slots were provided\n",
+			ARRAY_SIZE(vm_data->pt_pages), max_num_addrs);
 		return -EINVAL;
+	}
 
 	for (u32 page_nr = 0; page_nr < max_num_addrs; page_nr++) {
 		/* Firmware expects 4k pages, but host page size might be different. */

-- 
2.43.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/4] drm/imagination: Simplify MIPS PTE definitions
  2026-10-14  8:13 ` Alexandru Dadu
@ 2026-10-14  8:13   ` Alexandru Dadu
  -1 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu,
	Matt Coster

From: Matt Coster <matt.coster@imgtec.com>

Use BIT() and GENMASK() in the definitions of the MIPS PTE format, and
remove some unused definitions that add no value.

Signed-off-by: Matt Coster <matt.coster@imgtec.com>
Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
 drivers/gpu/drm/imagination/pvr_mips_internal.h | 72 ++++++++-----------------
 drivers/gpu/drm/imagination/pvr_vm_mips.c       | 25 ++++-----
 2 files changed, 34 insertions(+), 63 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_mips_internal.h b/drivers/gpu/drm/imagination/pvr_mips_internal.h
index 732730d64bf5..2b25a69003b3 100644
--- a/drivers/gpu/drm/imagination/pvr_mips_internal.h
+++ b/drivers/gpu/drm/imagination/pvr_mips_internal.h
@@ -39,63 +39,33 @@
 #define PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES (4)
 /* Total number of TLB entries. */
 #define PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES (16)
-/* "Uncached" caching policy. */
-#define PVR_MIPSFW_UNCACHED_CACHE_POLICY (2)
-/* "Write-back write-allocate" caching policy. */
-#define PVR_MIPSFW_WRITEBACK_CACHE_POLICY (3)
-/* "Write-through no write-allocate" caching policy. */
-#define PVR_MIPSFW_WRITETHROUGH_CACHE_POLICY (1)
+
+enum pvr_fw_mips_cache_policy {
+	/* "Write-through no write-allocate" caching policy. */
+	PVR_MIPSFW_CACHE_POLICY_WRITETHROUGH = 1,
+	/* "Uncached" caching policy. */
+	PVR_MIPSFW_CACHE_POLICY_UNCACHED = 2,
+	/* "Write-back write-allocate" caching policy. */
+	PVR_MIPSFW_CACHE_POLICY_WRITEBACK = 3,
+};
+
 /* Cached policy used by MIPS in case of physical bus on 32 bit. */
-#define PVR_MIPSFW_CACHED_POLICY (PVR_MIPSFW_WRITEBACK_CACHE_POLICY)
+#define PVR_MIPSFW_CACHE_POLICY_CACHED (PVR_MIPSFW_CACHE_POLICY_WRITEBACK)
 /* Cached policy used by MIPS in case of physical bus on more than 32 bit. */
-#define PVR_MIPSFW_CACHED_POLICY_ABOVE_32BIT (PVR_MIPSFW_WRITETHROUGH_CACHE_POLICY)
+#define PVR_MIPSFW_CACHE_POLICY_CACHED_ABOVE_32BIT (PVR_MIPSFW_CACHE_POLICY_WRITETHROUGH)
+
 /* Total number of Remap entries. */
 #define PVR_MIPSFW_NUMBER_OF_REMAP_ENTRIES (2 * PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES)
 
 /* MIPS EntryLo/PTE format. */
-
-#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_SHIFT (31U)
-#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_CLRMSK (0X7FFFFFFF)
-#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_EN (0X80000000)
-
-#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_SHIFT (30U)
-#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_CLRMSK (0XBFFFFFFF)
-#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_EN (0X40000000)
-
-/* Page Frame Number */
-#define PVR_MIPSFW_ENTRYLO_PFN_SHIFT (6)
-#define PVR_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT (12)
-/* Mask used for the MIPS Page Table in case of physical bus on 32 bit. */
-#define PVR_MIPSFW_ENTRYLO_PFN_MASK (0x03FFFFC0)
-#define PVR_MIPSFW_ENTRYLO_PFN_SIZE (20)
-/* Mask used for the MIPS Page Table in case of physical bus on more than 32 bit. */
-#define PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT (0x3FFFFFC0)
-#define PVR_MIPSFW_ENTRYLO_PFN_SIZE_ABOVE_32BIT (24)
-#define PVR_MIPSFW_ADDR_TO_ENTRYLO_PFN_RSHIFT (PVR_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT - \
-					       PVR_MIPSFW_ENTRYLO_PFN_SHIFT)
-
-#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT (3U)
-#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY_CLRMSK (0XFFFFFFC7)
-
-#define PVR_MIPSFW_ENTRYLO_DIRTY_SHIFT (2U)
-#define PVR_MIPSFW_ENTRYLO_DIRTY_CLRMSK (0XFFFFFFFB)
-#define PVR_MIPSFW_ENTRYLO_DIRTY_EN (0X00000004)
-
-#define PVR_MIPSFW_ENTRYLO_VALID_SHIFT (1U)
-#define PVR_MIPSFW_ENTRYLO_VALID_CLRMSK (0XFFFFFFFD)
-#define PVR_MIPSFW_ENTRYLO_VALID_EN (0X00000002)
-
-#define PVR_MIPSFW_ENTRYLO_GLOBAL_SHIFT (0U)
-#define PVR_MIPSFW_ENTRYLO_GLOBAL_CLRMSK (0XFFFFFFFE)
-#define PVR_MIPSFW_ENTRYLO_GLOBAL_EN (0X00000001)
-
-#define PVR_MIPSFW_ENTRYLO_DVG (PVR_MIPSFW_ENTRYLO_DIRTY_EN | \
-				PVR_MIPSFW_ENTRYLO_VALID_EN | \
-				PVR_MIPSFW_ENTRYLO_GLOBAL_EN)
-#define PVR_MIPSFW_ENTRYLO_UNCACHED (PVR_MIPSFW_UNCACHED_CACHE_POLICY << \
-				     PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT)
-#define PVR_MIPSFW_ENTRYLO_DVG_UNCACHED (PVR_MIPSFW_ENTRYLO_DVG | \
-					 PVR_MIPSFW_ENTRYLO_UNCACHED)
+#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT BIT_U32(31)
+#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT BIT_U32(30)
+#define PVR_MIPSFW_ENTRYLO_PFN GENMASK_U32(25, 6)
+#define PVR_MIPSFW_ENTRYLO_PFN_ABOVE_32BIT GENMASK_U32(29, 6)
+#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY GENMASK_U32(5, 3)
+#define PVR_MIPSFW_ENTRYLO_DIRTY BIT_U32(2)
+#define PVR_MIPSFW_ENTRYLO_VALID BIT_U32(1)
+#define PVR_MIPSFW_ENTRYLO_GLOBAL BIT_U32(0)
 
 /* Remap Range Config Addr Out. */
 /* These defines refer to the upper half of the Remap Range Config register. */
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
index 40495b1486a2..7f49314bc6be 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
@@ -97,11 +97,13 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)
 		goto err_free_pages;
 	}
 
-	vm_data->pfn_mask = (phys_bus_width > 32) ? PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
-						    PVR_MIPSFW_ENTRYLO_PFN_MASK;
-
-	vm_data->cache_policy = (phys_bus_width > 32) ? PVR_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
-							PVR_MIPSFW_CACHED_POLICY;
+	if (phys_bus_width > 32) {
+		vm_data->pfn_mask = PVR_MIPSFW_ENTRYLO_PFN_ABOVE_32BIT;
+		vm_data->cache_policy = PVR_MIPSFW_CACHE_POLICY_CACHED_ABOVE_32BIT;
+	} else {
+		vm_data->pfn_mask = PVR_MIPSFW_ENTRYLO_PFN;
+		vm_data->cache_policy = PVR_MIPSFW_CACHE_POLICY_CACHED;
+	}
 
 	pvr_dev->fw_dev.processor_data.mips_data.vm_data = vm_data;
 
@@ -145,15 +147,15 @@ get_mips_pte_flags(bool read, bool write, u32 cache_policy)
 	u32 flags = 0;
 
 	if (read && write) /* Read/write. */
-		flags |= PVR_MIPSFW_ENTRYLO_DIRTY_EN;
+		flags |= PVR_MIPSFW_ENTRYLO_DIRTY;
 	else if (write)    /* Write only. */
-		flags |= PVR_MIPSFW_ENTRYLO_READ_INHIBIT_EN;
+		flags |= PVR_MIPSFW_ENTRYLO_READ_INHIBIT;
 	else
 		WARN_ON(!read);
 
-	flags |= cache_policy << PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT;
+	flags |= FIELD_PREP(PVR_MIPSFW_ENTRYLO_CACHE_POLICY, cache_policy);
 
-	flags |= PVR_MIPSFW_ENTRYLO_VALID_EN | PVR_MIPSFW_ENTRYLO_GLOBAL_EN;
+	flags |= PVR_MIPSFW_ENTRYLO_VALID | PVR_MIPSFW_ENTRYLO_GLOBAL;
 
 	return flags;
 }
@@ -199,7 +201,7 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 	end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
 
 	if (pvr_obj->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
-		cache_policy = PVR_MIPSFW_UNCACHED_CACHE_POLICY;
+		cache_policy = PVR_MIPSFW_CACHE_POLICY_UNCACHED;
 	else
 		cache_policy = vm_data->cache_policy;
 
@@ -216,8 +218,7 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 		if (err)
 			goto err_unmap_pages;
 
-		pte = ((dma_addr >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
-		       << PVR_MIPSFW_ENTRYLO_PFN_SHIFT) & vm_data->pfn_mask;
+		pte = field_prep(vm_data->pfn_mask, dma_addr >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K);
 		pte |= pte_flags;
 
 		WRITE_ONCE(vm_data->pt[pfn], pte);

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/4] drm/imagination: Simplify MIPS PTE definitions
@ 2026-10-14  8:13   ` Alexandru Dadu
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandru Dadu @ 2026-10-14  8:13 UTC (permalink / raw)
  To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti
  Cc: linux-kernel, imagination, dri-devel, linux-riscv, Alexandru Dadu,
	Matt Coster

From: Matt Coster <matt.coster@imgtec.com>

Use BIT() and GENMASK() in the definitions of the MIPS PTE format, and
remove some unused definitions that add no value.

Signed-off-by: Matt Coster <matt.coster@imgtec.com>
Signed-off-by: Alexandru Dadu <alexandru.dadu@imgtec.com>
---
 drivers/gpu/drm/imagination/pvr_mips_internal.h | 72 ++++++++-----------------
 drivers/gpu/drm/imagination/pvr_vm_mips.c       | 25 ++++-----
 2 files changed, 34 insertions(+), 63 deletions(-)

diff --git a/drivers/gpu/drm/imagination/pvr_mips_internal.h b/drivers/gpu/drm/imagination/pvr_mips_internal.h
index 732730d64bf5..2b25a69003b3 100644
--- a/drivers/gpu/drm/imagination/pvr_mips_internal.h
+++ b/drivers/gpu/drm/imagination/pvr_mips_internal.h
@@ -39,63 +39,33 @@
 #define PVR_MIPSFW_MAX_NUM_PAGETABLE_PAGES (4)
 /* Total number of TLB entries. */
 #define PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES (16)
-/* "Uncached" caching policy. */
-#define PVR_MIPSFW_UNCACHED_CACHE_POLICY (2)
-/* "Write-back write-allocate" caching policy. */
-#define PVR_MIPSFW_WRITEBACK_CACHE_POLICY (3)
-/* "Write-through no write-allocate" caching policy. */
-#define PVR_MIPSFW_WRITETHROUGH_CACHE_POLICY (1)
+
+enum pvr_fw_mips_cache_policy {
+	/* "Write-through no write-allocate" caching policy. */
+	PVR_MIPSFW_CACHE_POLICY_WRITETHROUGH = 1,
+	/* "Uncached" caching policy. */
+	PVR_MIPSFW_CACHE_POLICY_UNCACHED = 2,
+	/* "Write-back write-allocate" caching policy. */
+	PVR_MIPSFW_CACHE_POLICY_WRITEBACK = 3,
+};
+
 /* Cached policy used by MIPS in case of physical bus on 32 bit. */
-#define PVR_MIPSFW_CACHED_POLICY (PVR_MIPSFW_WRITEBACK_CACHE_POLICY)
+#define PVR_MIPSFW_CACHE_POLICY_CACHED (PVR_MIPSFW_CACHE_POLICY_WRITEBACK)
 /* Cached policy used by MIPS in case of physical bus on more than 32 bit. */
-#define PVR_MIPSFW_CACHED_POLICY_ABOVE_32BIT (PVR_MIPSFW_WRITETHROUGH_CACHE_POLICY)
+#define PVR_MIPSFW_CACHE_POLICY_CACHED_ABOVE_32BIT (PVR_MIPSFW_CACHE_POLICY_WRITETHROUGH)
+
 /* Total number of Remap entries. */
 #define PVR_MIPSFW_NUMBER_OF_REMAP_ENTRIES (2 * PVR_MIPSFW_NUMBER_OF_TLB_ENTRIES)
 
 /* MIPS EntryLo/PTE format. */
-
-#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_SHIFT (31U)
-#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_CLRMSK (0X7FFFFFFF)
-#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT_EN (0X80000000)
-
-#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_SHIFT (30U)
-#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_CLRMSK (0XBFFFFFFF)
-#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT_EN (0X40000000)
-
-/* Page Frame Number */
-#define PVR_MIPSFW_ENTRYLO_PFN_SHIFT (6)
-#define PVR_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT (12)
-/* Mask used for the MIPS Page Table in case of physical bus on 32 bit. */
-#define PVR_MIPSFW_ENTRYLO_PFN_MASK (0x03FFFFC0)
-#define PVR_MIPSFW_ENTRYLO_PFN_SIZE (20)
-/* Mask used for the MIPS Page Table in case of physical bus on more than 32 bit. */
-#define PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT (0x3FFFFFC0)
-#define PVR_MIPSFW_ENTRYLO_PFN_SIZE_ABOVE_32BIT (24)
-#define PVR_MIPSFW_ADDR_TO_ENTRYLO_PFN_RSHIFT (PVR_MIPSFW_ENTRYLO_PFN_ALIGNSHIFT - \
-					       PVR_MIPSFW_ENTRYLO_PFN_SHIFT)
-
-#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT (3U)
-#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY_CLRMSK (0XFFFFFFC7)
-
-#define PVR_MIPSFW_ENTRYLO_DIRTY_SHIFT (2U)
-#define PVR_MIPSFW_ENTRYLO_DIRTY_CLRMSK (0XFFFFFFFB)
-#define PVR_MIPSFW_ENTRYLO_DIRTY_EN (0X00000004)
-
-#define PVR_MIPSFW_ENTRYLO_VALID_SHIFT (1U)
-#define PVR_MIPSFW_ENTRYLO_VALID_CLRMSK (0XFFFFFFFD)
-#define PVR_MIPSFW_ENTRYLO_VALID_EN (0X00000002)
-
-#define PVR_MIPSFW_ENTRYLO_GLOBAL_SHIFT (0U)
-#define PVR_MIPSFW_ENTRYLO_GLOBAL_CLRMSK (0XFFFFFFFE)
-#define PVR_MIPSFW_ENTRYLO_GLOBAL_EN (0X00000001)
-
-#define PVR_MIPSFW_ENTRYLO_DVG (PVR_MIPSFW_ENTRYLO_DIRTY_EN | \
-				PVR_MIPSFW_ENTRYLO_VALID_EN | \
-				PVR_MIPSFW_ENTRYLO_GLOBAL_EN)
-#define PVR_MIPSFW_ENTRYLO_UNCACHED (PVR_MIPSFW_UNCACHED_CACHE_POLICY << \
-				     PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT)
-#define PVR_MIPSFW_ENTRYLO_DVG_UNCACHED (PVR_MIPSFW_ENTRYLO_DVG | \
-					 PVR_MIPSFW_ENTRYLO_UNCACHED)
+#define PVR_MIPSFW_ENTRYLO_READ_INHIBIT BIT_U32(31)
+#define PVR_MIPSFW_ENTRYLO_EXEC_INHIBIT BIT_U32(30)
+#define PVR_MIPSFW_ENTRYLO_PFN GENMASK_U32(25, 6)
+#define PVR_MIPSFW_ENTRYLO_PFN_ABOVE_32BIT GENMASK_U32(29, 6)
+#define PVR_MIPSFW_ENTRYLO_CACHE_POLICY GENMASK_U32(5, 3)
+#define PVR_MIPSFW_ENTRYLO_DIRTY BIT_U32(2)
+#define PVR_MIPSFW_ENTRYLO_VALID BIT_U32(1)
+#define PVR_MIPSFW_ENTRYLO_GLOBAL BIT_U32(0)
 
 /* Remap Range Config Addr Out. */
 /* These defines refer to the upper half of the Remap Range Config register. */
diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
index 40495b1486a2..7f49314bc6be 100644
--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
+++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
@@ -97,11 +97,13 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)
 		goto err_free_pages;
 	}
 
-	vm_data->pfn_mask = (phys_bus_width > 32) ? PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT :
-						    PVR_MIPSFW_ENTRYLO_PFN_MASK;
-
-	vm_data->cache_policy = (phys_bus_width > 32) ? PVR_MIPSFW_CACHED_POLICY_ABOVE_32BIT :
-							PVR_MIPSFW_CACHED_POLICY;
+	if (phys_bus_width > 32) {
+		vm_data->pfn_mask = PVR_MIPSFW_ENTRYLO_PFN_ABOVE_32BIT;
+		vm_data->cache_policy = PVR_MIPSFW_CACHE_POLICY_CACHED_ABOVE_32BIT;
+	} else {
+		vm_data->pfn_mask = PVR_MIPSFW_ENTRYLO_PFN;
+		vm_data->cache_policy = PVR_MIPSFW_CACHE_POLICY_CACHED;
+	}
 
 	pvr_dev->fw_dev.processor_data.mips_data.vm_data = vm_data;
 
@@ -145,15 +147,15 @@ get_mips_pte_flags(bool read, bool write, u32 cache_policy)
 	u32 flags = 0;
 
 	if (read && write) /* Read/write. */
-		flags |= PVR_MIPSFW_ENTRYLO_DIRTY_EN;
+		flags |= PVR_MIPSFW_ENTRYLO_DIRTY;
 	else if (write)    /* Write only. */
-		flags |= PVR_MIPSFW_ENTRYLO_READ_INHIBIT_EN;
+		flags |= PVR_MIPSFW_ENTRYLO_READ_INHIBIT;
 	else
 		WARN_ON(!read);
 
-	flags |= cache_policy << PVR_MIPSFW_ENTRYLO_CACHE_POLICY_SHIFT;
+	flags |= FIELD_PREP(PVR_MIPSFW_ENTRYLO_CACHE_POLICY, cache_policy);
 
-	flags |= PVR_MIPSFW_ENTRYLO_VALID_EN | PVR_MIPSFW_ENTRYLO_GLOBAL_EN;
+	flags |= PVR_MIPSFW_ENTRYLO_VALID | PVR_MIPSFW_ENTRYLO_GLOBAL;
 
 	return flags;
 }
@@ -199,7 +201,7 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 	end_pfn = (end & fw_dev->fw_heap_info.offset_mask) >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K;
 
 	if (pvr_obj->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
-		cache_policy = PVR_MIPSFW_UNCACHED_CACHE_POLICY;
+		cache_policy = PVR_MIPSFW_CACHE_POLICY_UNCACHED;
 	else
 		cache_policy = vm_data->cache_policy;
 
@@ -216,8 +218,7 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
 		if (err)
 			goto err_unmap_pages;
 
-		pte = ((dma_addr >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K)
-		       << PVR_MIPSFW_ENTRYLO_PFN_SHIFT) & vm_data->pfn_mask;
+		pte = field_prep(vm_data->pfn_mask, dma_addr >> PVR_MIPSFW_LOG2_PAGE_SIZE_4K);
 		pte |= pte_flags;
 
 		WRITE_ONCE(vm_data->pt[pfn], pte);

-- 
2.43.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/4] drm/imagination: Limit access to the MIPS firmware interface
  2026-10-14  8:13   ` Alexandru Dadu
  (?)
@ 2026-10-14  8:32   ` sashiko-bot
  -1 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-10-14  8:32 UTC (permalink / raw)
  To: Alexandru Dadu; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] drm/imagination: kernel panic in pvr_vm_mips_map() on 64KB-page systems due to 0-page vmap
--

commit f751c0095eefbac6525746590080b3626f16f23d
Author: Alessio Belle <alessio.belle@imgtec.com>

drm/imagination: Limit access to the MIPS firmware interface

This commit restricts access to the MIPS firmware interface by using the
generic firmware interface or the MIPS-specific VM interface. It splits the
pvr_fw_mips_data struct into internal structures and removes the public
MIPS firmware interface header.

> diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
> index 5847a1c92bea8..264ea0fccf9c1 100644
> --- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
> +++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
> @@ -43,49 +69,49 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)

[ ... ]

> -	mips_data->pt = vmap(mips_data->pt_pages, pt_size >> PAGE_SHIFT, VM_MAP,
> -			     pgprot_writecombine(PAGE_KERNEL));
> -	if (!mips_data->pt) {
> +	vm_data->pt = vmap(vm_data->pt_pages, pt_size >> PAGE_SHIFT, VM_MAP,
> +			   pgprot_writecombine(PAGE_KERNEL));
> +	if (!vm_data->pt) {

[Severity: High]
Does this code handle architectures with 64KB pages correctly?

During DRM driver initialization, pvr_vm_mips_init() allocates firmware
page tables. The page table size pt_size evaluates to 16384 bytes (16KB).
When vmap() is called here, pt_size >> PAGE_SHIFT evaluates to 0 on
architectures with 64KB pages (PAGE_SHIFT=16). Passing a 0 page count to
vmap() returns a non-NULL pointer to an unmapped guard page area.

> @@ -190,10 +216,10 @@ pvr_vm_mips_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
>  			goto err_unmap_pages;
>  
>  		pte = ((dma_addr >> ROGUE_MIPSFW_LOG2_PAGE_SIZE_4K)
> -		       << ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT) & mips_data->pfn_mask;
> +		       << ROGUE_MIPSFW_ENTRYLO_PFN_SHIFT) & vm_data->pfn_mask;
>  		pte |= pte_flags;
>  
> -		WRITE_ONCE(mips_data->pt[pfn], pte);
> +		WRITE_ONCE(vm_data->pt[pfn], pte);

[Severity: High]
Can this write trigger a kernel panic on 64KB-page systems?

If vm_data->pt points to an unmapped guard page returned by vmap() due to
the 0 page count, writing to vm_data->pt[pfn] here will dereference that
unmapped address and cause a page fault.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261014-b4-simplify-mips-pte-defs-v1-0-b4ad7bb68e22@imgtec.com?part=1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 4/4] drm/imagination: Simplify MIPS PTE definitions
  2026-10-14  8:13   ` Alexandru Dadu
  (?)
@ 2026-10-14  8:34   ` sashiko-bot
  -1 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-10-14  8:34 UTC (permalink / raw)
  To: Alexandru Dadu; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] mm: PTE state consistency violation in get_mips_pte_flags() for write-only mappings
- [Low] drm/imagination: Broken macro reference in PVR_MIPSFW_TLB_GET_PA
--

commit a6fd7c6870a5757f18024650beba88d0d531dd3a
Author: Matt Coster <opensource@mtcoster.net>

drm/imagination: Simplify MIPS PTE definitions

This commit simplifies the MIPS PTE format definitions by using BIT() and
GENMASK() macros. It also removes some unused definitions that add no value.

> diff --git a/drivers/gpu/drm/imagination/pvr_mips_internal.h b/drivers/gpu/drm/imagination/pvr_mips_internal.h
> index 732730d64bf54..2b25a69003b31 100644
> --- a/drivers/gpu/drm/imagination/pvr_mips_internal.h
> +++ b/drivers/gpu/drm/imagination/pvr_mips_internal.h
[ ... ]
> -/* Mask used for the MIPS Page Table in case of physical bus on more than 32 bit. */
> -#define PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT (0x3FFFFFC0)
[ ... ]
> +#define PVR_MIPSFW_ENTRYLO_PFN_ABOVE_32BIT GENMASK_U32(29, 6)

[Severity: Low]
Could this deletion break compilation for PVR_MIPSFW_TLB_GET_PA()?

While the macro PVR_MIPSFW_TLB_GET_PA() isn't used in this patch, it still
references the deleted PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT constant in
drivers/gpu/drm/imagination/pvr_mips_internal.h:

#define PVR_MIPSFW_TLB_GET_PA(entry_lo) (((u64)(entry_lo) & \
					  PVR_MIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT) << 6)

Leaving a broken macro with an undeclared identifier could cause an immediate
compilation failure if any future code attempts to use it.

> diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
> index 40495b1486a26..7f49314bc6be4 100644
> --- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
> +++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
[ ... ]
> @@ -145,15 +147,15 @@ get_mips_pte_flags(bool read, bool write, u32 cache_policy)
>  	u32 flags = 0;
>  
>  	if (read && write) /* Read/write. */
> -		flags |= PVR_MIPSFW_ENTRYLO_DIRTY_EN;
> +		flags |= PVR_MIPSFW_ENTRYLO_DIRTY;
>  	else if (write)    /* Write only. */
> -		flags |= PVR_MIPSFW_ENTRYLO_READ_INHIBIT_EN;
> +		flags |= PVR_MIPSFW_ENTRYLO_READ_INHIBIT;

[Severity: Medium]
Will this construct a non-writable mapping for write-only pages?

For MIPS hardware, the DIRTY bit functions as the hardware write-enable bit,
and a writable PTE must have this bit set; otherwise, any store operation
triggers a TLB Modified exception.

In this write-only branch in get_mips_pte_flags(), the code sets
PVR_MIPSFW_ENTRYLO_READ_INHIBIT but fails to set PVR_MIPSFW_ENTRYLO_DIRTY.
This will cause firmware writes to these pages to trap and crash the
firmware. Should this branch also set the DIRTY bit?

>  	else
>  		WARN_ON(!read);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261014-b4-simplify-mips-pte-defs-v1-0-b4ad7bb68e22@imgtec.com?part=4

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-10-14  8:35 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14  8:13 [PATCH 0/4] drm/imagination: Clean up MIPS firmware interfaces Alexandru Dadu
2026-10-14  8:13 ` Alexandru Dadu
2026-10-14  8:13 ` [PATCH 1/4] drm/imagination: Limit access to the MIPS firmware interface Alexandru Dadu
2026-10-14  8:13   ` Alexandru Dadu
2026-10-14  8:32   ` sashiko-bot
2026-10-14  8:13 ` [PATCH 2/4] drm/imagination: Make the MIPS firmware headers arch-independent Alexandru Dadu
2026-10-14  8:13   ` Alexandru Dadu
2026-10-14  8:13 ` [PATCH 3/4] drm/imagination: Improve some logging in error paths Alexandru Dadu
2026-10-14  8:13   ` Alexandru Dadu
2026-10-14  8:13 ` [PATCH 4/4] drm/imagination: Simplify MIPS PTE definitions Alexandru Dadu
2026-10-14  8:13   ` Alexandru Dadu
2026-10-14  8:34   ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.