lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251022-topic-adreno-attach-gmu-to-driver-v1-1-999037f7c83e@linaro.org>
Date: Wed, 22 Oct 2025 14:44:40 +0200
From: Neil Armstrong <neil.armstrong@...aro.org>
To: Rob Clark <robin.clark@....qualcomm.com>, Sean Paul <sean@...rly.run>, 
 Konrad Dybcio <konradybcio@...nel.org>, Dmitry Baryshkov <lumag@...nel.org>, 
 Abhinav Kumar <abhinav.kumar@...ux.dev>, 
 Jessica Zhang <jessica.zhang@....qualcomm.com>, 
 Marijn Suijten <marijn.suijten@...ainline.org>, 
 David Airlie <airlied@...il.com>, Simona Vetter <simona@...ll.ch>
Cc: linux-arm-msm@...r.kernel.org, dri-devel@...ts.freedesktop.org, 
 freedreno@...ts.freedesktop.org, linux-kernel@...r.kernel.org, 
 Neil Armstrong <neil.armstrong@...aro.org>
Subject: [PATCH RFC RFT] drm/msm: adreno: attach the GMU device to a driver

Due to the sync_state is enabled by default in pmdomain & CCF since v6.17,
the GCC and GPUCC sync_state would stay pending, leaving the resources in
full performance:
gcc-x1e80100 100000.clock-controller: sync_state() pending due to 3d6a000.gmu
gpucc-x1e80100 3d90000.clock-controller: sync_state() pending due to 3d6a000.gmu

In order to fix this state and allow the GMU to be properly
probed, let's add a proper driver for the GMU and add it to
the MSM driver components.

Only the proper GMU has been tested since I don't have
access to hardware with a GMU wrapper.

Signed-off-by: Neil Armstrong <neil.armstrong@...aro.org>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c      | 354 ++++++++++++++---------------
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c      |   6 -
 drivers/gpu/drm/msm/adreno/a6xx_gpu.h      |   3 -
 drivers/gpu/drm/msm/adreno/adreno_device.c |   4 +
 drivers/gpu/drm/msm/adreno/adreno_gpu.h    |   4 +
 drivers/gpu/drm/msm/msm_drv.c              |  16 +-
 6 files changed, 192 insertions(+), 195 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index fc62fef2fed8..6e7c3e627509 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1859,11 +1859,14 @@ void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu)
 	pm_runtime_put(&gpu->pdev->dev);
 }
 
-void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
+static void a6xx_gmu_unbind(struct device *dev, struct device *master, void *data)
 {
-	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct msm_drm_private *priv = dev_get_drvdata(master);
+	struct msm_gpu *gpu = priv->gpu;
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
 	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
-	struct platform_device *pdev = to_platform_device(gmu->dev);
 
 	mutex_lock(&gmu->lock);
 	if (!gmu->initialized) {
@@ -1903,9 +1906,6 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
 		free_irq(gmu->gmu_irq, gmu);
 		free_irq(gmu->hfi_irq, gmu);
 	}
-
-	/* Drop reference taken in of_find_device_by_node */
-	put_device(gmu->dev);
 }
 
 static int cxpd_notifier_cb(struct notifier_block *nb,
@@ -1919,169 +1919,130 @@ static int cxpd_notifier_cb(struct notifier_block *nb,
 	return 0;
 }
 
-int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
+static int a6xx_gmu_bind(struct device *dev, struct device *master, void *data)
 {
-	struct platform_device *pdev = of_find_device_by_node(node);
-	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
-	int ret;
-
-	if (!pdev)
-		return -ENODEV;
-
-	gmu->dev = &pdev->dev;
-
-	ret = of_dma_configure(gmu->dev, node, true);
-	if (ret)
-		return ret;
-
-	pm_runtime_enable(gmu->dev);
-
-	/* Mark legacy for manual SPTPRAC control */
-	gmu->legacy = true;
-
-	/* Map the GMU registers */
-	gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
-	if (IS_ERR(gmu->mmio)) {
-		ret = PTR_ERR(gmu->mmio);
-		goto err_mmio;
-	}
-
-	gmu->cxpd = dev_pm_domain_attach_by_name(gmu->dev, "cx");
-	if (IS_ERR(gmu->cxpd)) {
-		ret = PTR_ERR(gmu->cxpd);
-		goto err_mmio;
-	}
-
-	if (!device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME)) {
-		ret = -ENODEV;
-		goto detach_cxpd;
-	}
-
-	init_completion(&gmu->pd_gate);
-	complete_all(&gmu->pd_gate);
-	gmu->pd_nb.notifier_call = cxpd_notifier_cb;
-
-	/* Get a link to the GX power domain to reset the GPU */
-	gmu->gxpd = dev_pm_domain_attach_by_name(gmu->dev, "gx");
-	if (IS_ERR(gmu->gxpd)) {
-		ret = PTR_ERR(gmu->gxpd);
-		goto err_mmio;
-	}
-
-	gmu->initialized = true;
-
-	return 0;
-
-detach_cxpd:
-	dev_pm_domain_detach(gmu->cxpd, false);
-
-err_mmio:
-	iounmap(gmu->mmio);
-
-	/* Drop reference taken in of_find_device_by_node */
-	put_device(gmu->dev);
-
-	return ret;
-}
-
-int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
-{
-	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct msm_drm_private *priv = dev_get_drvdata(master);
+	struct msm_gpu *gpu = dev_to_gpu(&priv->gpu_pdev->dev);
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
 	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
-	struct platform_device *pdev = of_find_device_by_node(node);
 	struct device_link *link;
 	int ret;
 
-	if (!pdev)
-		return -ENODEV;
-
-	gmu->dev = &pdev->dev;
+	gmu->dev = dev;
 
-	ret = of_dma_configure(gmu->dev, node, true);
+	ret = of_dma_configure(gmu->dev, dev->of_node, true);
 	if (ret)
 		return ret;
 
-	/* Set GMU idle level */
-	gmu->idle_level = (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) ?
-		GMU_IDLE_STATE_IFPC : GMU_IDLE_STATE_ACTIVE;
+	if (adreno_has_gmu_wrapper(adreno_gpu))
+		/* Mark legacy for manual SPTPRAC control */
+		gmu->legacy = true;
+
+	if (!gmu->legacy)
+		/* Set GMU idle level */
+		gmu->idle_level = (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) ?
+			GMU_IDLE_STATE_IFPC : GMU_IDLE_STATE_ACTIVE;
 
 	pm_runtime_enable(gmu->dev);
 
-	/* Get the list of clocks */
-	ret = a6xx_gmu_clocks_probe(gmu);
-	if (ret)
-		goto err_put_device;
+	if (!gmu->legacy) {
+		/* Get the list of clocks */
+		ret = a6xx_gmu_clocks_probe(gmu);
+		if (ret)
+			return ret;
 
-	ret = a6xx_gmu_memory_probe(adreno_gpu->base.dev, gmu);
-	if (ret)
-		goto err_put_device;
+		ret = a6xx_gmu_memory_probe(adreno_gpu->base.dev, gmu);
+		if (ret)
+			return ret;
 
+		/* A660 now requires handling "prealloc requests" in GMU firmware
+		 * For now just hardcode allocations based on the known firmware.
+		 * note: there is no indication that these correspond to "dummy" or
+		 * "debug" regions, but this "guess" allows reusing these BOs which
+		 * are otherwise unused by a660.
+		 */
+		gmu->dummy.size = SZ_4K;
+		if (adreno_is_a660_family(adreno_gpu) ||
+		    adreno_is_a7xx(adreno_gpu)) {
+			ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_4K * 7,
+						    0x60400000, "debug");
+			if (ret)
+				goto err_memory;
+
+			gmu->dummy.size = SZ_8K;
+		}
 
-	/* A660 now requires handling "prealloc requests" in GMU firmware
-	 * For now just hardcode allocations based on the known firmware.
-	 * note: there is no indication that these correspond to "dummy" or
-	 * "debug" regions, but this "guess" allows reusing these BOs which
-	 * are otherwise unused by a660.
-	 */
-	gmu->dummy.size = SZ_4K;
-	if (adreno_is_a660_family(adreno_gpu) ||
-	    adreno_is_a7xx(adreno_gpu)) {
-		ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_4K * 7,
-					    0x60400000, "debug");
+		/* Allocate memory for the GMU dummy page */
+		ret = a6xx_gmu_memory_alloc(gmu, &gmu->dummy, gmu->dummy.size,
+					    0x60000000, "dummy");
 		if (ret)
 			goto err_memory;
 
-		gmu->dummy.size = SZ_8K;
-	}
-
-	/* Allocate memory for the GMU dummy page */
-	ret = a6xx_gmu_memory_alloc(gmu, &gmu->dummy, gmu->dummy.size,
-				    0x60000000, "dummy");
-	if (ret)
-		goto err_memory;
+		/* Note that a650 family also includes a660 family: */
+		if (adreno_is_a650_family(adreno_gpu) ||
+		    adreno_is_a7xx(adreno_gpu)) {
+			ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache,
+				SZ_16M - SZ_16K, 0x04000, "icache");
+			if (ret)
+				goto err_memory;
+		/*
+		 * NOTE: when porting legacy ("pre-650-family") GPUs you may be tempted to add a condition
+		 * to allocate icache/dcache here, as per downstream code flow, but it may not actually be
+		 * necessary. If you omit this step and you don't get random pagefaults, you are likely
+		 * good to go without this!
+		 */
+		} else if (adreno_is_a640_family(adreno_gpu)) {
+			ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache,
+				SZ_256K - SZ_16K, 0x04000, "icache");
+			if (ret)
+				goto err_memory;
+
+			ret = a6xx_gmu_memory_alloc(gmu, &gmu->dcache,
+				SZ_256K - SZ_16K, 0x44000, "dcache");
+			if (ret)
+				goto err_memory;
+		} else if (adreno_is_a630_family(adreno_gpu)) {
+			/* HFI v1, has sptprac */
+			gmu->legacy = true;
+
+			/* Allocate memory for the GMU debug region */
+			ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_16K, 0, "debug");
+			if (ret)
+				goto err_memory;
+		}
 
-	/* Note that a650 family also includes a660 family: */
-	if (adreno_is_a650_family(adreno_gpu) ||
-	    adreno_is_a7xx(adreno_gpu)) {
-		ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache,
-			SZ_16M - SZ_16K, 0x04000, "icache");
-		if (ret)
-			goto err_memory;
-	/*
-	 * NOTE: when porting legacy ("pre-650-family") GPUs you may be tempted to add a condition
-	 * to allocate icache/dcache here, as per downstream code flow, but it may not actually be
-	 * necessary. If you omit this step and you don't get random pagefaults, you are likely
-	 * good to go without this!
-	 */
-	} else if (adreno_is_a640_family(adreno_gpu)) {
-		ret = a6xx_gmu_memory_alloc(gmu, &gmu->icache,
-			SZ_256K - SZ_16K, 0x04000, "icache");
+		/* Allocate memory for the GMU log region */
+		ret = a6xx_gmu_memory_alloc(gmu, &gmu->log, SZ_16K, 0, "log");
 		if (ret)
 			goto err_memory;
 
-		ret = a6xx_gmu_memory_alloc(gmu, &gmu->dcache,
-			SZ_256K - SZ_16K, 0x44000, "dcache");
+		/* Allocate memory for for the HFI queues */
+		ret = a6xx_gmu_memory_alloc(gmu, &gmu->hfi, SZ_16K, 0, "hfi");
 		if (ret)
 			goto err_memory;
-	} else if (adreno_is_a630_family(adreno_gpu)) {
-		/* HFI v1, has sptprac */
-		gmu->legacy = true;
 
-		/* Allocate memory for the GMU debug region */
-		ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_16K, 0, "debug");
-		if (ret)
-			goto err_memory;
-	}
+		if (adreno_is_a650_family(adreno_gpu) ||
+		    adreno_is_a7xx(adreno_gpu)) {
+			gmu->rscc = a6xx_gmu_get_mmio(pdev, "rscc");
+			if (IS_ERR(gmu->rscc)) {
+				ret = -ENODEV;
+				goto err_mmio;
+			}
+		} else {
+			gmu->rscc = gmu->mmio + 0x23000;
+		}
 
-	/* Allocate memory for the GMU log region */
-	ret = a6xx_gmu_memory_alloc(gmu, &gmu->log, SZ_16K, 0, "log");
-	if (ret)
-		goto err_memory;
+		/* Get the HFI and GMU interrupts */
+		gmu->hfi_irq = a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq);
+		gmu->gmu_irq = a6xx_gmu_get_irq(gmu, pdev, "gmu", a6xx_gmu_irq);
 
-	/* Allocate memory for for the HFI queues */
-	ret = a6xx_gmu_memory_alloc(gmu, &gmu->hfi, SZ_16K, 0, "hfi");
-	if (ret)
-		goto err_memory;
+		if (gmu->hfi_irq < 0 || gmu->gmu_irq < 0) {
+			ret = -ENODEV;
+			goto err_mmio;
+		}
+	}
 
 	/* Map the GMU registers */
 	gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
@@ -2090,26 +2051,6 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 		goto err_memory;
 	}
 
-	if (adreno_is_a650_family(adreno_gpu) ||
-	    adreno_is_a7xx(adreno_gpu)) {
-		gmu->rscc = a6xx_gmu_get_mmio(pdev, "rscc");
-		if (IS_ERR(gmu->rscc)) {
-			ret = -ENODEV;
-			goto err_mmio;
-		}
-	} else {
-		gmu->rscc = gmu->mmio + 0x23000;
-	}
-
-	/* Get the HFI and GMU interrupts */
-	gmu->hfi_irq = a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq);
-	gmu->gmu_irq = a6xx_gmu_get_irq(gmu, pdev, "gmu", a6xx_gmu_irq);
-
-	if (gmu->hfi_irq < 0 || gmu->gmu_irq < 0) {
-		ret = -ENODEV;
-		goto err_mmio;
-	}
-
 	gmu->cxpd = dev_pm_domain_attach_by_name(gmu->dev, "cx");
 	if (IS_ERR(gmu->cxpd)) {
 		ret = PTR_ERR(gmu->cxpd);
@@ -2122,11 +2063,13 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 		goto detach_cxpd;
 	}
 
-	/* Other errors are handled during GPU ACD probe */
-	gmu->qmp = qmp_get(gmu->dev);
-	if (PTR_ERR_OR_ZERO(gmu->qmp) == -EPROBE_DEFER) {
-		ret = -EPROBE_DEFER;
-		goto detach_gxpd;
+	if (!gmu->legacy) {
+		/* Other errors are handled during GPU ACD probe */
+		gmu->qmp = qmp_get(gmu->dev);
+		if (PTR_ERR_OR_ZERO(gmu->qmp) == -EPROBE_DEFER) {
+			ret = -EPROBE_DEFER;
+			goto detach_gxpd;
+		}
 	}
 
 	init_completion(&gmu->pd_gate);
@@ -2139,18 +2082,20 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	 */
 	gmu->gxpd = dev_pm_domain_attach_by_name(gmu->dev, "gx");
 
-	/* Get the power levels for the GMU and GPU */
-	a6xx_gmu_pwrlevels_probe(gmu);
+	if (!gmu->legacy) {
+		/* Get the power levels for the GMU and GPU */
+		a6xx_gmu_pwrlevels_probe(gmu);
 
-	ret = a6xx_gmu_acd_probe(gmu);
-	if (ret)
-		goto detach_gxpd;
+		ret = a6xx_gmu_acd_probe(gmu);
+		if (ret)
+			goto detach_gxpd;
 
-	/* Set up the HFI queues */
-	a6xx_hfi_init(gmu);
+		/* Set up the HFI queues */
+		a6xx_hfi_init(gmu);
 
-	/* Initialize RPMh */
-	a6xx_gmu_rpmh_init(gmu);
+		/* Initialize RPMh */
+		a6xx_gmu_rpmh_init(gmu);
+	}
 
 	gmu->initialized = true;
 
@@ -2170,16 +2115,57 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 
 err_mmio:
 	iounmap(gmu->mmio);
-	if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc"))
-		iounmap(gmu->rscc);
-	free_irq(gmu->gmu_irq, gmu);
-	free_irq(gmu->hfi_irq, gmu);
+	if (!gmu->legacy) {
+		if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "rscc"))
+			iounmap(gmu->rscc);
+		free_irq(gmu->gmu_irq, gmu);
+		free_irq(gmu->hfi_irq, gmu);
+	}
 
 err_memory:
-	a6xx_gmu_memory_free(gmu);
-err_put_device:
-	/* Drop reference taken in of_find_device_by_node */
-	put_device(gmu->dev);
+	if (!gmu->legacy)
+		a6xx_gmu_memory_free(gmu);
 
 	return ret;
 }
+
+static const struct component_ops a6xx_gmu_ops = {
+	.bind   = a6xx_gmu_bind,
+	.unbind = a6xx_gmu_unbind,
+};
+
+static int a6xx_gmu_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &a6xx_gmu_ops);
+}
+
+static void a6xx_gmu_remove(struct platform_device *pdev)
+{
+
+	component_del(&pdev->dev, &a6xx_gmu_ops);
+}
+
+static const struct of_device_id dt_match[] = {
+	{ .compatible = "qcom,adreno-gmu" },
+	{ .compatible = "qcom,adreno-gmu-wrapper" },
+	{}
+};
+
+static struct platform_driver a6xx_gmu_drv = {
+	.probe = a6xx_gmu_probe,
+	.remove = a6xx_gmu_remove,
+	.driver = {
+		.name = "a6xx_gmu",
+		.of_match_table = dt_match,
+	},
+};
+
+void __init a6xx_gmu_register(void)
+{
+	platform_driver_register(&a6xx_gmu_drv);
+}
+
+void __exit a6xx_gmu_unregister(void)
+{
+	platform_driver_unregister(&a6xx_gmu_drv);
+}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index b8f8ae940b55..d418f49f47a1 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -2352,8 +2352,6 @@ static void a6xx_destroy(struct msm_gpu *gpu)
 
 	a6xx_llc_slices_destroy(a6xx_gpu);
 
-	a6xx_gmu_remove(a6xx_gpu);
-
 	adreno_gpu_cleanup(adreno_gpu);
 
 	kfree(a6xx_gpu);
@@ -2689,10 +2687,6 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
 	if (adreno_is_a618(adreno_gpu) || adreno_is_7c3(adreno_gpu))
 		priv->gpu_clamp_to_idle = true;
 
-	if (adreno_has_gmu_wrapper(adreno_gpu))
-		ret = a6xx_gmu_wrapper_init(a6xx_gpu, node);
-	else
-		ret = a6xx_gmu_init(a6xx_gpu, node);
 	of_node_put(node);
 	if (ret) {
 		a6xx_destroy(&(a6xx_gpu->base.base));
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index 0b17d36c36a9..070af413e5ad 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -252,9 +252,6 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu);
 int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
 void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
 
-int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
-int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
-void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
 void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu);
 
 void a6xx_preempt_init(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 28f744f3caf7..9f9b5863a8de 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -415,6 +415,8 @@ void __init adreno_register(void)
 		return;
 
 	platform_driver_register(&adreno_driver);
+
+	a6xx_gmu_register();
 }
 
 void __exit adreno_unregister(void)
@@ -422,5 +424,7 @@ void __exit adreno_unregister(void)
 	if (skip_gpu)
 		return;
 
+	a6xx_gmu_unregister();
+
 	platform_driver_unregister(&adreno_driver);
 }
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 390fa6720d9b..d3a653adbc72 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -678,6 +678,10 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
 struct msm_gpu *a4xx_gpu_init(struct drm_device *dev);
 struct msm_gpu *a5xx_gpu_init(struct drm_device *dev);
 struct msm_gpu *a6xx_gpu_init(struct drm_device *dev);
+struct msm_gpu *a6xx_gpu_init(struct drm_device *dev);
+
+void __init a6xx_gmu_register(void);
+void __exit a6xx_gmu_unregister(void);
 
 static inline uint32_t get_wptr(struct msm_ringbuffer *ring)
 {
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 7e977fec4100..0618da7e8b40 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -998,18 +998,30 @@ static const struct of_device_id msm_gpu_match[] = {
 	{ },
 };
 
+static const struct of_device_id msm_gmu_match[] = {
+	{ .compatible = "qcom,adreno-gmu" },
+	{ .compatible = "qcom,adreno-gmu-wrapper" },
+	{ },
+};
+
 static int add_gpu_components(struct device *dev,
 			      struct component_match **matchptr)
 {
-	struct device_node *np;
+	struct device_node *np, *gmu;
 
 	np = of_find_matching_node(NULL, msm_gpu_match);
 	if (!np)
 		return 0;
 
-	if (of_device_is_available(np) && adreno_has_gpu(np))
+	if (of_device_is_available(np) && adreno_has_gpu(np)) {
 		drm_of_component_match_add(dev, matchptr, component_compare_of, np);
 
+		gmu = of_find_matching_node(NULL, msm_gmu_match);
+		if (of_device_is_available(gmu))
+			drm_of_component_match_add(dev, matchptr, component_compare_of, gmu);
+		of_node_put(gmu);
+	}
+
 	of_node_put(np);
 
 	return 0;

---
base-commit: 211ddde0823f1442e4ad052a2f30f050145ccada
change-id: 20251022-topic-adreno-attach-gmu-to-driver-e47025fd7ebb

Best regards,
-- 
Neil Armstrong <neil.armstrong@...aro.org>


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ