From nobody Mon Feb 9 19:54:32 2026 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 73A91344039 for ; Wed, 22 Oct 2025 12:44:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761137087; cv=none; b=Puxaq1hbs6mFChj2SpVn9OGc9s8MNnLtUvnO7ZGs5OI1s3WdgZ4s1Szd8HqJYLczeG2hkhj4YOIAd7XJVcnCkgf0sQ7gk9fx8UqYqacy4SGsMWmnzil3XBmR5NUTKXEkGspgqFI+O9V+BshaXPo6+T96SA6Me6PIDwEx4+chXjw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761137087; c=relaxed/simple; bh=xiZscMSJ5Y6S51NdfEoM5uux4TkxuaNsK2jqNgL5eL8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=UNDoAedCk1REFqZlP2MwQPgvqvSIdGlehgJ8NKDQI4tdjd1iLj/V7WD+Inw8WTJeV5PFaJt4DD09E9C7R3G/LrlfAchTRaMwVftvGfna7KUEnUbey+x3dLQJBv5b4EdyL9W5+qjmWQkqrgnZVzeTW1YdFpOkoDriJP4Bti149H4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=W6tVF3fK; arc=none smtp.client-ip=209.85.221.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="W6tVF3fK" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-4270a0127e1so3398797f8f.3 for ; Wed, 22 Oct 2025 05:44:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1761137083; x=1761741883; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:from:to:cc:subject:date:message-id:reply-to; bh=/lszp+0t1XNimB1Wor5aJTBDq6Y010S2Qxr+PcGktvc=; b=W6tVF3fKO4ImAaAxJEjtZ/oASSYM0ebDwpw7QMOtIxAbXiywIU1M86DpejQ3QktAPc WR5HD/X+t9evaF8G2j0uAGHBugDuJifPuYFxiGkoQGe33dbT9S7BovHEdsPHYweozSup LFKcl8SbrwDUTV6LPjLxmPvOMDGpVJddsrnrDbtn/AYjQP2F+oyp4JLQ5FdN7ZwKGxVo ns1nCjrgltvaXky4ANG7wAdzSjVgOTGci3zJUvcxhl2AT5HJ8j978g2AeUCOgXdMSn9R k8HBbpIb8ajR9jMyarOmbFfid041sWLC11f6JO3IVEMRDLVdIK/IwfOByQH7GOKbUt6X fAWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761137083; x=1761741883; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=/lszp+0t1XNimB1Wor5aJTBDq6Y010S2Qxr+PcGktvc=; b=l1IHHvhdXK8mHJ6VWUZaz9Tc/N0vMCI3FPspt1guaNB+3Kv0yMA55id3BWqoz3VLhu RFWT3DZ7jtippneu+eWLnAMZ6QEy7luXRtsRPhGbW0oFHZGN/Pnb6YkQpWs5m8zcF7Rz jEl4Rjxad7F0FDntFhDJJT/AdI1MsGbT1Dz7tDFpQsldLf6pFlkXXCW0/PjuNqu4SRM1 0fi8016D2VHRucwDKMF+FCFYoG8e1URPMfxWrFxxeGOg6ShQSe1lXkBNVL+ATryicNfg EJnuHw9jYNdnANDtiPnWO7OWyHgFXC6mG3CKTq+zL1sRrCqRKVvohwvd1a2K7UO1g8/k 1YAA== X-Forwarded-Encrypted: i=1; AJvYcCVY5f74Mwuvh+XRoaxg6/m/QMw011N3MCyBI7/Cf+lk7WhYqtNPwXbMh/82iuNzIARaPvpmIN7S/sYov/A=@vger.kernel.org X-Gm-Message-State: AOJu0YynVI9YdC/rANiTk9R6jR872fpZfjlidnzQTgh1nYYF2N5PWRf4 +1J0r4u5aD0ZoSZz1WE4srcatWtm+WJOFGlCBBS+p+eKI2f5wXmppEEaef6IVm7G628= X-Gm-Gg: ASbGncsqCv1DTF1UVzZ9J9tOk5FwTaemrFI5Vylp58Cr5dcEA9OE3HMPV8s22cqX7Lz cGjECYFro35u6609sMf2kAhWvADELZrJryxx9MA1JADXL9Iu0FUWArXIhRanSfXX07ORX022fM/ cgJNHm+z3RVmsW7W/+7wk+awGNlQ1X3IVKm21b8QiSNv0H0iWv6rMd9Ok60dsO8UjxNoOrs90sL jBR+/PY38RQFvzv+NXfs7U8eKWmvj5IQLjoln/miKvl0CRoGyQN+MWSKspSZYGrW5v8ZDN5/asH 5xaxXB2Cxna2WKopymZGwkhZNrANQnPW6orLDL8sA7oIrVA7zDjoCWIwkpmpFl7xqBPW4c4kA5g NbN9AZdmc7hj5wkgkhEMX3xKRWv2IR9XWLqxIEtkyu9U1h6Bv3+2eKiQHXQ0rOBoMgXCgra4XVU YM86ylNxQLNSRfDYRW5cwN X-Google-Smtp-Source: AGHT+IEeJnQTJSqadBx3d8e4XA6eI7t/KljcdJTu95OhpQjf/JKTRr/Lu38tHgjoWOKhwCvC0wMRQg== X-Received: by 2002:a05:6000:1869:b0:427:79f:dcd8 with SMTP id ffacd0b85a97d-427079fdd00mr13043419f8f.55.1761137082390; Wed, 22 Oct 2025 05:44:42 -0700 (PDT) Received: from arrakeen.starnux.net ([2a01:e0a:3d9:2080:52eb:f6ff:feb3:451a]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-427f00ce586sm25647844f8f.49.2025.10.22.05.44.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Oct 2025 05:44:41 -0700 (PDT) From: Neil Armstrong Date: Wed, 22 Oct 2025 14:44:40 +0200 Subject: [PATCH RFC RFT] drm/msm: adreno: attach the GMU device to a driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-topic-adreno-attach-gmu-to-driver-v1-1-999037f7c83e@linaro.org> X-B4-Tracking: v=1; b=H4sIALfR+GgC/x2NQQqDMBBFryKz7oCGitCt4AGku9JFTEadhYlMU hHEuzt2+R6f9w9IJEwJXsUBQhsnjkGhehTgZhsmQvbKYEpTV6UxmOPKDq0XChFtztbNOC0/9ei FNxKkZ6Pj0Tc0DKCdVWjk/f/xgb5rb9d3b/ie5wViHSYUfwAAAA== X-Change-ID: 20251022-topic-adreno-attach-gmu-to-driver-e47025fd7ebb To: Rob Clark , Sean Paul , Konrad Dybcio , Dmitry Baryshkov , Abhinav Kumar , Jessica Zhang , Marijn Suijten , David Airlie , Simona Vetter Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org, Neil Armstrong X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=18606; i=neil.armstrong@linaro.org; h=from:subject:message-id; bh=xiZscMSJ5Y6S51NdfEoM5uux4TkxuaNsK2jqNgL5eL8=; b=owEBbQKS/ZANAwAKAXfc29rIyEnRAcsmYgBo+NG5aoKCA+c8tB7YzGfS59IwHnAbyd5SliF3bRTh m+LdECaJAjMEAAEKAB0WIQQ9U8YmyFYF/h30LIt33NvayMhJ0QUCaPjRuQAKCRB33NvayMhJ0W9AD/ 94SMt/rsFa602UkRpKch70/ZJCRrdTvkCRwPGXyySIHJSlzZR726o5IGl9M4mHyEv9hVZf3Wy69VbB /bBM2FkuAuTKtrfNay7RIv4Sz31BCryP+n+pU6bcFMSyxIF225N4zu5QNaky67xxn6GXkV69Qo0gWc BjkRlaESBUZxBZrzK5vapPeVKVcpo/xT8vfr5iLcaf8bE9oR90vAQIdEbXJcoeKNuWEURrAC/ydAL8 8e9YWhqgPnj3eC0L7WpJ+Aq+i9jcVwryrQxTdykpTVec9fsol5q8yxqBEYmgHlu/6bEuiEr5CU6rNg NNNnAEe/CmCheuzdiRMtXXgpXYrzyWBpclPs74833efU/x/oIP/h5LlFC5ETrMdR9TiBi4xSOYtP4K RfIXJFBlepiLtA2SoChgXGOMUA3ggov2WI0bhcyob9AmRE3kF2PYpaXwFuO3A3hO6KAat1ddx+F2vk Aqk+ia7YFOlptZ7C0359UM3dDwMh71m7UKdoEjwRJN6p6KCGzEWCPsenPLzg4eMhjKYCbEOe1b4KrY WFMiy3MOr6fuGUS3I5NNr3PIjqum90go0MUAm/W0Xc5qaooyJogXNv+uyFfg9KWa3mE3p3mSKs2y3Y thT+BSuz7TNbVVAovKmQhPwbQmTR8AuvNV3UgviCnnabOul8ZOilysLzq5lQ== X-Developer-Key: i=neil.armstrong@linaro.org; a=openpgp; fpr=89EC3D058446217450F22848169AB7B1A4CFF8AE 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.g= mu gpucc-x1e80100 3d90000.clock-controller: sync_state() pending due to 3d6a00= 0.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 --- 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/ad= reno/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); } =20 -void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu) +static void a6xx_gmu_unbind(struct device *dev, struct device *master, voi= d *data) { - struct adreno_gpu *adreno_gpu =3D &a6xx_gpu->base; + struct platform_device *pdev =3D to_platform_device(dev); + struct msm_drm_private *priv =3D dev_get_drvdata(master); + struct msm_gpu *gpu =3D priv->gpu; + struct adreno_gpu *adreno_gpu =3D to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu =3D to_a6xx_gpu(adreno_gpu); struct a6xx_gmu *gmu =3D &a6xx_gpu->gmu; - struct platform_device *pdev =3D to_platform_device(gmu->dev); =20 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); } =20 static int cxpd_notifier_cb(struct notifier_block *nb, @@ -1919,169 +1919,130 @@ static int cxpd_notifier_cb(struct notifier_block= *nb, return 0; } =20 -int a6xx_gmu_wrapper_init(struct a6xx_gpu *a6xx_gpu, struct device_node *n= ode) +static int a6xx_gmu_bind(struct device *dev, struct device *master, void *= data) { - struct platform_device *pdev =3D of_find_device_by_node(node); - struct a6xx_gmu *gmu =3D &a6xx_gpu->gmu; - int ret; - - if (!pdev) - return -ENODEV; - - gmu->dev =3D &pdev->dev; - - ret =3D of_dma_configure(gmu->dev, node, true); - if (ret) - return ret; - - pm_runtime_enable(gmu->dev); - - /* Mark legacy for manual SPTPRAC control */ - gmu->legacy =3D true; - - /* Map the GMU registers */ - gmu->mmio =3D a6xx_gmu_get_mmio(pdev, "gmu"); - if (IS_ERR(gmu->mmio)) { - ret =3D PTR_ERR(gmu->mmio); - goto err_mmio; - } - - gmu->cxpd =3D dev_pm_domain_attach_by_name(gmu->dev, "cx"); - if (IS_ERR(gmu->cxpd)) { - ret =3D PTR_ERR(gmu->cxpd); - goto err_mmio; - } - - if (!device_link_add(gmu->dev, gmu->cxpd, DL_FLAG_PM_RUNTIME)) { - ret =3D -ENODEV; - goto detach_cxpd; - } - - init_completion(&gmu->pd_gate); - complete_all(&gmu->pd_gate); - gmu->pd_nb.notifier_call =3D cxpd_notifier_cb; - - /* Get a link to the GX power domain to reset the GPU */ - gmu->gxpd =3D dev_pm_domain_attach_by_name(gmu->dev, "gx"); - if (IS_ERR(gmu->gxpd)) { - ret =3D PTR_ERR(gmu->gxpd); - goto err_mmio; - } - - gmu->initialized =3D 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 =3D &a6xx_gpu->base; + struct platform_device *pdev =3D to_platform_device(dev); + struct msm_drm_private *priv =3D dev_get_drvdata(master); + struct msm_gpu *gpu =3D dev_to_gpu(&priv->gpu_pdev->dev); + struct adreno_gpu *adreno_gpu =3D to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu =3D to_a6xx_gpu(adreno_gpu); struct a6xx_gmu *gmu =3D &a6xx_gpu->gmu; - struct platform_device *pdev =3D of_find_device_by_node(node); struct device_link *link; int ret; =20 - if (!pdev) - return -ENODEV; - - gmu->dev =3D &pdev->dev; + gmu->dev =3D dev; =20 - ret =3D of_dma_configure(gmu->dev, node, true); + ret =3D of_dma_configure(gmu->dev, dev->of_node, true); if (ret) return ret; =20 - /* Set GMU idle level */ - gmu->idle_level =3D (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 =3D true; + + if (!gmu->legacy) + /* Set GMU idle level */ + gmu->idle_level =3D (adreno_gpu->info->quirks & ADRENO_QUIRK_IFPC) ? + GMU_IDLE_STATE_IFPC : GMU_IDLE_STATE_ACTIVE; =20 pm_runtime_enable(gmu->dev); =20 - /* Get the list of clocks */ - ret =3D a6xx_gmu_clocks_probe(gmu); - if (ret) - goto err_put_device; + if (!gmu->legacy) { + /* Get the list of clocks */ + ret =3D a6xx_gmu_clocks_probe(gmu); + if (ret) + return ret; =20 - ret =3D a6xx_gmu_memory_probe(adreno_gpu->base.dev, gmu); - if (ret) - goto err_put_device; + ret =3D a6xx_gmu_memory_probe(adreno_gpu->base.dev, gmu); + if (ret) + return ret; =20 + /* 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 =3D SZ_4K; + if (adreno_is_a660_family(adreno_gpu) || + adreno_is_a7xx(adreno_gpu)) { + ret =3D a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_4K * 7, + 0x60400000, "debug"); + if (ret) + goto err_memory; + + gmu->dummy.size =3D SZ_8K; + } =20 - /* 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 =3D SZ_4K; - if (adreno_is_a660_family(adreno_gpu) || - adreno_is_a7xx(adreno_gpu)) { - ret =3D a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_4K * 7, - 0x60400000, "debug"); + /* Allocate memory for the GMU dummy page */ + ret =3D a6xx_gmu_memory_alloc(gmu, &gmu->dummy, gmu->dummy.size, + 0x60000000, "dummy"); if (ret) goto err_memory; =20 - gmu->dummy.size =3D SZ_8K; - } - - /* Allocate memory for the GMU dummy page */ - ret =3D 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 =3D 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 m= ay 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 =3D a6xx_gmu_memory_alloc(gmu, &gmu->icache, + SZ_256K - SZ_16K, 0x04000, "icache"); + if (ret) + goto err_memory; + + ret =3D 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 =3D true; + + /* Allocate memory for the GMU debug region */ + ret =3D a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_16K, 0, "debug"); + if (ret) + goto err_memory; + } =20 - /* Note that a650 family also includes a660 family: */ - if (adreno_is_a650_family(adreno_gpu) || - adreno_is_a7xx(adreno_gpu)) { - ret =3D 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 t= o add a condition - * to allocate icache/dcache here, as per downstream code flow, but it ma= y 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 =3D a6xx_gmu_memory_alloc(gmu, &gmu->icache, - SZ_256K - SZ_16K, 0x04000, "icache"); + /* Allocate memory for the GMU log region */ + ret =3D a6xx_gmu_memory_alloc(gmu, &gmu->log, SZ_16K, 0, "log"); if (ret) goto err_memory; =20 - ret =3D a6xx_gmu_memory_alloc(gmu, &gmu->dcache, - SZ_256K - SZ_16K, 0x44000, "dcache"); + /* Allocate memory for for the HFI queues */ + ret =3D 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 =3D true; =20 - /* Allocate memory for the GMU debug region */ - ret =3D 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 =3D a6xx_gmu_get_mmio(pdev, "rscc"); + if (IS_ERR(gmu->rscc)) { + ret =3D -ENODEV; + goto err_mmio; + } + } else { + gmu->rscc =3D gmu->mmio + 0x23000; + } =20 - /* Allocate memory for the GMU log region */ - ret =3D 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 =3D a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq); + gmu->gmu_irq =3D a6xx_gmu_get_irq(gmu, pdev, "gmu", a6xx_gmu_irq); =20 - /* Allocate memory for for the HFI queues */ - ret =3D 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 =3D -ENODEV; + goto err_mmio; + } + } =20 /* Map the GMU registers */ gmu->mmio =3D 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; } =20 - if (adreno_is_a650_family(adreno_gpu) || - adreno_is_a7xx(adreno_gpu)) { - gmu->rscc =3D a6xx_gmu_get_mmio(pdev, "rscc"); - if (IS_ERR(gmu->rscc)) { - ret =3D -ENODEV; - goto err_mmio; - } - } else { - gmu->rscc =3D gmu->mmio + 0x23000; - } - - /* Get the HFI and GMU interrupts */ - gmu->hfi_irq =3D a6xx_gmu_get_irq(gmu, pdev, "hfi", a6xx_hfi_irq); - gmu->gmu_irq =3D a6xx_gmu_get_irq(gmu, pdev, "gmu", a6xx_gmu_irq); - - if (gmu->hfi_irq < 0 || gmu->gmu_irq < 0) { - ret =3D -ENODEV; - goto err_mmio; - } - gmu->cxpd =3D dev_pm_domain_attach_by_name(gmu->dev, "cx"); if (IS_ERR(gmu->cxpd)) { ret =3D PTR_ERR(gmu->cxpd); @@ -2122,11 +2063,13 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct= device_node *node) goto detach_cxpd; } =20 - /* Other errors are handled during GPU ACD probe */ - gmu->qmp =3D qmp_get(gmu->dev); - if (PTR_ERR_OR_ZERO(gmu->qmp) =3D=3D -EPROBE_DEFER) { - ret =3D -EPROBE_DEFER; - goto detach_gxpd; + if (!gmu->legacy) { + /* Other errors are handled during GPU ACD probe */ + gmu->qmp =3D qmp_get(gmu->dev); + if (PTR_ERR_OR_ZERO(gmu->qmp) =3D=3D -EPROBE_DEFER) { + ret =3D -EPROBE_DEFER; + goto detach_gxpd; + } } =20 init_completion(&gmu->pd_gate); @@ -2139,18 +2082,20 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct= device_node *node) */ gmu->gxpd =3D dev_pm_domain_attach_by_name(gmu->dev, "gx"); =20 - /* 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); =20 - ret =3D a6xx_gmu_acd_probe(gmu); - if (ret) - goto detach_gxpd; + ret =3D a6xx_gmu_acd_probe(gmu); + if (ret) + goto detach_gxpd; =20 - /* Set up the HFI queues */ - a6xx_hfi_init(gmu); + /* Set up the HFI queues */ + a6xx_hfi_init(gmu); =20 - /* Initialize RPMh */ - a6xx_gmu_rpmh_init(gmu); + /* Initialize RPMh */ + a6xx_gmu_rpmh_init(gmu); + } =20 gmu->initialized =3D true; =20 @@ -2170,16 +2115,57 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct= device_node *node) =20 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); + } =20 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); =20 return ret; } + +static const struct component_ops a6xx_gmu_ops =3D { + .bind =3D a6xx_gmu_bind, + .unbind =3D 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[] =3D { + { .compatible =3D "qcom,adreno-gmu" }, + { .compatible =3D "qcom,adreno-gmu-wrapper" }, + {} +}; + +static struct platform_driver a6xx_gmu_drv =3D { + .probe =3D a6xx_gmu_probe, + .remove =3D a6xx_gmu_remove, + .driver =3D { + .name =3D "a6xx_gmu", + .of_match_table =3D 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/ad= reno/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) =20 a6xx_llc_slices_destroy(a6xx_gpu); =20 - a6xx_gmu_remove(a6xx_gpu); - adreno_gpu_cleanup(adreno_gpu); =20 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 =3D true; =20 - if (adreno_has_gmu_wrapper(adreno_gpu)) - ret =3D a6xx_gmu_wrapper_init(a6xx_gpu, node); - else - ret =3D 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/ad= reno/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 stat= e); =20 -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 *n= ode); -void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu); void a6xx_gmu_sysprof_setup(struct msm_gpu *gpu); =20 void a6xx_preempt_init(struct msm_gpu *gpu); diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/m= sm/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; =20 platform_driver_register(&adreno_driver); + + a6xx_gmu_register(); } =20 void __exit adreno_unregister(void) @@ -422,5 +424,7 @@ void __exit adreno_unregister(void) if (skip_gpu) return; =20 + 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); =20 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[] =3D { { }, }; =20 +static const struct of_device_id msm_gmu_match[] =3D { + { .compatible =3D "qcom,adreno-gmu" }, + { .compatible =3D "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; =20 np =3D of_find_matching_node(NULL, msm_gpu_match); if (!np) return 0; =20 - 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); =20 + gmu =3D 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); =20 return 0; --- base-commit: 211ddde0823f1442e4ad052a2f30f050145ccada change-id: 20251022-topic-adreno-attach-gmu-to-driver-e47025fd7ebb Best regards, --=20 Neil Armstrong