diff --git a/drivers/gpu/drm/imagination/pvr_device.c b/drivers/gpu/drm/imagination/pvr_device.c
index 52d7641a1a0c62a9c4029092e846472d82950a61..2ce46b9a8ab7609faebeeb4e7820751b00047806 100644
--- a/drivers/gpu/drm/imagination/pvr_device.c
+++ b/drivers/gpu/drm/imagination/pvr_device.c
@@ -621,3 +621,29 @@ pvr_device_has_feature(struct pvr_device *pvr_dev, u32 feature)
 		return false;
 	}
 }
+
+/**
+ * pvr_device_overrides_validate() - Ensure the overrides specified are compatible with a device.
+ * @pvr_dev: Target PowerVR device.
+ * @overrides: Device overrides to validate.
+ *
+ * Return:
+ *  * %true if every override specified in @overrides is compatible with the current device, or
+ *  * %false otherwise; as many incompatibilities as possible will be reported in the kernel log.
+ */
+bool
+pvr_device_overrides_validate(struct pvr_device *pvr_dev,
+			      const struct pvr_device_overrides *overrides)
+{
+	bool ret = true;
+
+	/*
+	 * Where possible, avoid early returns in this function. This allows for as
+	 * many errors to be reported at once as possible.
+	 *
+	 * Note that this function may be called early during device initialization
+	 * so it should not be assumed that @pvr_dev is ready for normal use yet.
+	 */
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/imagination/pvr_device.h b/drivers/gpu/drm/imagination/pvr_device.h
index 76f79b18af354f0e0070530dfc5c8fe0f6a41ce1..ad0a02a37154099542247dfc62f411c10f4e41f4 100644
--- a/drivers/gpu/drm/imagination/pvr_device.h
+++ b/drivers/gpu/drm/imagination/pvr_device.h
@@ -16,6 +16,7 @@
 #include <drm/drm_mm.h>
 
 #include <linux/bits.h>
+#include <linux/compiler.h>
 #include <linux/compiler_attributes.h>
 #include <linux/compiler_types.h>
 #include <linux/device.h>
@@ -56,6 +57,13 @@ struct pvr_fw_version {
 	u16 major, minor;
 };
 
+/**
+ * struct pvr_device_overrides - Hardware-level overrides loaded from
+ * MODULE_DEVICE_TABLE() or similar.
+ */
+struct pvr_device_overrides {
+};
+
 /**
  * struct pvr_device - powervr-specific wrapper for &struct drm_device
  */
@@ -94,6 +102,13 @@ struct pvr_device {
 	 */
 	struct pvr_device_enhancements enhancements;
 
+	/**
+	 * @overrides: Platform-specific overrides required for this device.
+	 *
+	 * Do not access this member directly, instead use PVR_HAS_OVERRIDE().
+	 */
+	struct pvr_device_overrides overrides;
+
 	/** @fw_version: Firmware version detected at runtime. */
 	struct pvr_fw_version fw_version;
 
@@ -436,6 +451,13 @@ struct pvr_file {
  */
 #define PVR_HAS_ENHANCEMENT(pvr_dev, enhancement) ((pvr_dev)->enhancements.has_ern##enhancement)
 
+/**
+ * PVR_HAS_OVERRIDE() - Tests whether a physical device requires a given override
+ * @pvr_dev: [IN] Target PowerVR device.
+ * @override: [IN] Override name.
+ */
+#define PVR_HAS_OVERRIDE(pvr_dev, override) unlikely((pvr_dev)->overrides.override)
+
 #define from_pvr_device(pvr_dev) (&(pvr_dev)->base)
 
 #define to_pvr_device(drm_dev) container_of_const(drm_dev, struct pvr_device, base)
@@ -516,6 +538,10 @@ pvr_device_has_uapi_enhancement(struct pvr_device *pvr_dev, u32 enhancement);
 bool
 pvr_device_has_feature(struct pvr_device *pvr_dev, u32 feature);
 
+bool
+pvr_device_overrides_validate(struct pvr_device *pvr_dev,
+			      const struct pvr_device_overrides *overrides);
+
 /**
  * PVR_CR_FIELD_GET() - Extract a single field from a PowerVR control register
  * @val: Value of the target register.
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 1ab97933e14f20ee3fbf603c23b8dde2d33572c2..b56ee2cda9b54c4388a6eef38b0ff81acdb05874 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -31,6 +31,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
@@ -1396,11 +1397,13 @@ static struct drm_driver pvr_drm_driver = {
 static int
 pvr_probe(struct platform_device *plat_dev)
 {
+	const struct pvr_device_overrides *overrides;
+	struct device *dev = &plat_dev->dev;
 	struct pvr_device *pvr_dev;
 	struct drm_device *drm_dev;
 	int err;
 
-	pvr_dev = devm_drm_dev_alloc(&plat_dev->dev, &pvr_drm_driver,
+	pvr_dev = devm_drm_dev_alloc(dev, &pvr_drm_driver,
 				     struct pvr_device, base);
 	if (IS_ERR(pvr_dev))
 		return PTR_ERR(pvr_dev);
@@ -1409,6 +1412,15 @@ pvr_probe(struct platform_device *plat_dev)
 
 	platform_set_drvdata(plat_dev, drm_dev);
 
+	overrides = of_device_get_match_data(dev);
+	if (!overrides)
+		return -EINVAL;
+
+	if (!pvr_device_overrides_validate(pvr_dev, overrides))
+		return -EINVAL;
+
+	pvr_dev->overrides = *overrides;
+
 	err = pvr_power_domains_init(pvr_dev);
 	if (err)
 		goto err_context_fini;
@@ -1421,11 +1433,11 @@ pvr_probe(struct platform_device *plat_dev)
 	if (err)
 		goto err_power_domains_fini;
 
-	devm_pm_runtime_enable(&plat_dev->dev);
-	pm_runtime_mark_last_busy(&plat_dev->dev);
+	devm_pm_runtime_enable(dev);
+	pm_runtime_mark_last_busy(dev);
 
-	pm_runtime_set_autosuspend_delay(&plat_dev->dev, 50);
-	pm_runtime_use_autosuspend(&plat_dev->dev);
+	pm_runtime_set_autosuspend_delay(dev, 50);
+	pm_runtime_use_autosuspend(dev);
 	pvr_watchdog_init(pvr_dev);
 
 	err = pvr_device_init(pvr_dev);
@@ -1478,18 +1490,24 @@ static void pvr_remove(struct platform_device *plat_dev)
 	pvr_power_domains_fini(pvr_dev);
 }
 
+static const struct pvr_device_overrides pvr_device_overrides_default = {};
+
+/*
+ * Always specify &pvr_device_overrides_default instead of %NULL for &struct of_device_id->data so
+ * that we know of_device_get_match_data() returning %NULL is an error.
+ */
 static const struct of_device_id dt_match[] = {
-	{ .compatible = "img,img-rogue", .data = NULL },
+	{ .compatible = "img,img-rogue", .data = &pvr_device_overrides_default },
 
 	/* All supported GPU models */
-	{ .compatible = "img,img-axe-1-16m", .data = NULL },
+	{ .compatible = "img,img-axe-1-16m", .data = &pvr_device_overrides_default },
 
 	/*
 	 * This legacy compatible string was introduced early on before the more specific GPU
 	 * identifiers were used. Keep it around here for compatibility, but never use
 	 * "img,img-axe" in new devicetrees.
 	 */
-	{ .compatible = "img,img-axe", .data = NULL },
+	{ .compatible = "img,img-axe", .data = &pvr_device_overrides_default },
 	{}
 };
 MODULE_DEVICE_TABLE(of, dt_match);
