dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/9] drm/msm/adreno: add A640/A650 to gpulist
       [not found] <20200420140313.7263-1-jonathan@marek.ca>
@ 2020-04-20 14:03 ` Jonathan Marek
  2020-04-20 14:30   ` Greg Kroah-Hartman
  2020-04-20 14:03 ` [PATCH 2/9] Revert "drm/msm/a6xx: Use the DMA API for GMU memory objects" Jonathan Marek
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 14:03 UTC (permalink / raw)
  To: freedreno
  Cc: Wambui Karuga, Douglas Anderson, open list, Jeffrey Hugo,
	David Airlie, Greg Kroah-Hartman, Sharat Masetty,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Bjorn Andersson,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Thomas Gleixner,
	AngeloGioacchino Del Regno, Sean Paul, Allison Randal,
	Brian Masney

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 24 ++++++++++++++++++++++
 drivers/gpu/drm/msm/adreno/adreno_gpu.c    |  2 +-
 drivers/gpu/drm/msm/adreno/adreno_gpu.h    | 10 +++++++++
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index cb3a6e597d76..1156f72532a4 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -189,6 +189,30 @@ static const struct adreno_info gpulist[] = {
 		.inactive_period = DRM_MSM_INACTIVE_PERIOD,
 		.init = a6xx_gpu_init,
 		.zapfw = "a630_zap.mdt",
+	}, {
+		.rev = ADRENO_REV(6, 4, 0, ANY_ID),
+		.revn = 640,
+		.name = "A640",
+		.fw = {
+			[ADRENO_FW_SQE] = "a630_sqe.fw",
+			[ADRENO_FW_GMU] = "a640_gmu.bin",
+		},
+		.gmem = SZ_1M,
+		.inactive_period = DRM_MSM_INACTIVE_PERIOD,
+		.init = a6xx_gpu_init,
+		.zapfw = "a640_zap.mdt",
+	}, {
+		.rev = ADRENO_REV(6, 5, 0, ANY_ID),
+		.revn = 650,
+		.name = "A650",
+		.fw = {
+			[ADRENO_FW_SQE] = "a650_sqe.fw",
+			[ADRENO_FW_GMU] = "a650_gmu.bin",
+		},
+		.gmem = SZ_1M + SZ_128K,
+		.inactive_period = DRM_MSM_INACTIVE_PERIOD,
+		.init = a6xx_gpu_init,
+		.zapfw = "a650_zap.mdt",
 	},
 };
 
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 1d5c43c22269..a7647eaacc7a 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -197,7 +197,7 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
 		*value = adreno_gpu->gmem;
 		return 0;
 	case MSM_PARAM_GMEM_BASE:
-		*value = 0x100000;
+		*value = !adreno_is_a650(adreno_gpu) ? 0x100000 : 0;
 		return 0;
 	case MSM_PARAM_CHIP_ID:
 		*value = adreno_gpu->rev.patchid |
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 9ff4e550e7bd..88ae1b2813ef 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -237,6 +237,16 @@ static inline int adreno_is_a630(struct adreno_gpu *gpu)
        return gpu->revn == 630;
 }
 
+static inline int adreno_is_a640(struct adreno_gpu *gpu)
+{
+       return gpu->revn == 640;
+}
+
+static inline int adreno_is_a650(struct adreno_gpu *gpu)
+{
+       return gpu->revn == 650;
+}
+
 int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
 const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu,
 		const char *fwname);
-- 
2.26.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 2/9] Revert "drm/msm/a6xx: Use the DMA API for GMU memory objects"
       [not found] <20200420140313.7263-1-jonathan@marek.ca>
  2020-04-20 14:03 ` [PATCH 1/9] drm/msm/adreno: add A640/A650 to gpulist Jonathan Marek
@ 2020-04-20 14:03 ` Jonathan Marek
  2020-04-20 19:51   ` Bjorn Andersson
  2020-04-20 14:03 ` [PATCH 3/9] drm/msm/a6xx: allow allocating GMU memory with a fixed address Jonathan Marek
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 14:03 UTC (permalink / raw)
  To: freedreno
  Cc: David Airlie, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sharat Masetty, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Stephen Boyd, Michael J. Ruhl, Sean Paul, open list

This reverts commit a5fb8b918920c6f7706a8b5b8ea535a7f077a7f6.
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 115 +++++++++++++++++++++++---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h |   6 +-
 2 files changed, 107 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index c4e71abbdd53..748cd379065f 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -2,7 +2,6 @@
 /* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */
 
 #include <linux/clk.h>
-#include <linux/dma-mapping.h>
 #include <linux/interconnect.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_opp.h>
@@ -921,10 +920,21 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
 
 static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo)
 {
+	int count, i;
+	u64 iova;
+
 	if (IS_ERR_OR_NULL(bo))
 		return;
 
-	dma_free_wc(gmu->dev, bo->size, bo->virt, bo->iova);
+	count = bo->size >> PAGE_SHIFT;
+	iova = bo->iova;
+
+	for (i = 0; i < count; i++, iova += PAGE_SIZE) {
+		iommu_unmap(gmu->domain, iova, PAGE_SIZE);
+		__free_pages(bo->pages[i], 0);
+	}
+
+	kfree(bo->pages);
 	kfree(bo);
 }
 
@@ -932,6 +942,7 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
 		size_t size)
 {
 	struct a6xx_gmu_bo *bo;
+	int ret, count, i;
 
 	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
 	if (!bo)
@@ -939,14 +950,86 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
 
 	bo->size = PAGE_ALIGN(size);
 
-	bo->virt = dma_alloc_wc(gmu->dev, bo->size, &bo->iova, GFP_KERNEL);
+	count = bo->size >> PAGE_SHIFT;
 
-	if (!bo->virt) {
+	bo->pages = kcalloc(count, sizeof(struct page *), GFP_KERNEL);
+	if (!bo->pages) {
 		kfree(bo);
 		return ERR_PTR(-ENOMEM);
 	}
 
+	for (i = 0; i < count; i++) {
+		bo->pages[i] = alloc_page(GFP_KERNEL);
+		if (!bo->pages[i])
+			goto err;
+	}
+
+	bo->iova = gmu->uncached_iova_base;
+
+	for (i = 0; i < count; i++) {
+		ret = iommu_map(gmu->domain,
+			bo->iova + (PAGE_SIZE * i),
+			page_to_phys(bo->pages[i]), PAGE_SIZE,
+			IOMMU_READ | IOMMU_WRITE);
+
+		if (ret) {
+			DRM_DEV_ERROR(gmu->dev, "Unable to map GMU buffer object\n");
+
+			for (i = i - 1 ; i >= 0; i--)
+				iommu_unmap(gmu->domain,
+					bo->iova + (PAGE_SIZE * i),
+					PAGE_SIZE);
+
+			goto err;
+		}
+	}
+
+	bo->virt = vmap(bo->pages, count, VM_IOREMAP,
+		pgprot_writecombine(PAGE_KERNEL));
+	if (!bo->virt)
+		goto err;
+
+	/* Align future IOVA addresses on 1MB boundaries */
+	gmu->uncached_iova_base += ALIGN(size, SZ_1M);
+
 	return bo;
+
+err:
+	for (i = 0; i < count; i++) {
+		if (bo->pages[i])
+			__free_pages(bo->pages[i], 0);
+	}
+
+	kfree(bo->pages);
+	kfree(bo);
+
+	return ERR_PTR(-ENOMEM);
+}
+
+static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu)
+{
+	int ret;
+
+	/*
+	 * The GMU address space is hardcoded to treat the range
+	 * 0x60000000 - 0x80000000 as un-cached memory. All buffers shared
+	 * between the GMU and the CPU will live in this space
+	 */
+	gmu->uncached_iova_base = 0x60000000;
+
+
+	gmu->domain = iommu_domain_alloc(&platform_bus_type);
+	if (!gmu->domain)
+		return -ENODEV;
+
+	ret = iommu_attach_device(gmu->domain, gmu->dev);
+
+	if (ret) {
+		iommu_domain_free(gmu->domain);
+		gmu->domain = NULL;
+	}
+
+	return ret;
 }
 
 /* Return the 'arc-level' for the given frequency */
@@ -1206,6 +1289,10 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
 
 	a6xx_gmu_memory_free(gmu, gmu->hfi);
 
+	iommu_detach_device(gmu->domain, gmu->dev);
+
+	iommu_domain_free(gmu->domain);
+
 	free_irq(gmu->gmu_irq, gmu);
 	free_irq(gmu->hfi_irq, gmu);
 
@@ -1226,15 +1313,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 
 	gmu->dev = &pdev->dev;
 
-	/* Pass force_dma false to require the DT to set the dma region */
-	ret = of_dma_configure(gmu->dev, node, false);
-	if (ret)
-		return ret;
-
-	/* Set the mask after the of_dma_configure() */
-	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(31));
-	if (ret)
-		return ret;
+	of_dma_configure(gmu->dev, node, true);
 
 	/* Fow now, don't do anything fancy until we get our feet under us */
 	gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
@@ -1246,6 +1325,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	if (ret)
 		goto err_put_device;
 
+	/* Set up the IOMMU context bank */
+	ret = a6xx_gmu_memory_probe(gmu);
+	if (ret)
+		goto err_put_device;
+
 	/* Allocate memory for for the HFI queues */
 	gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K);
 	if (IS_ERR(gmu->hfi))
@@ -1291,6 +1375,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 err_memory:
 	a6xx_gmu_memory_free(gmu, gmu->hfi);
 
+	if (gmu->domain) {
+		iommu_detach_device(gmu->domain, gmu->dev);
+
+		iommu_domain_free(gmu->domain);
+	}
 	ret = -ENODEV;
 
 err_put_device:
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 4af65a36d5ca..2af91ed7ed0c 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -12,7 +12,8 @@
 struct a6xx_gmu_bo {
 	void *virt;
 	size_t size;
-	dma_addr_t iova;
+	u64 iova;
+	struct page **pages;
 };
 
 /*
@@ -48,6 +49,9 @@ struct a6xx_gmu {
 	int hfi_irq;
 	int gmu_irq;
 
+	struct iommu_domain *domain;
+	u64 uncached_iova_base;
+
 	struct device *gxpd;
 
 	int idle_level;
-- 
2.26.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 3/9] drm/msm/a6xx: allow allocating GMU memory with a fixed address
       [not found] <20200420140313.7263-1-jonathan@marek.ca>
  2020-04-20 14:03 ` [PATCH 1/9] drm/msm/adreno: add A640/A650 to gpulist Jonathan Marek
  2020-04-20 14:03 ` [PATCH 2/9] Revert "drm/msm/a6xx: Use the DMA API for GMU memory objects" Jonathan Marek
@ 2020-04-20 14:03 ` Jonathan Marek
  2020-04-20 14:03 ` [PATCH 4/9] drm/msm/a6xx: HFI v2 for A640 and A650 Jonathan Marek
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 14:03 UTC (permalink / raw)
  To: freedreno
  Cc: David Airlie, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sharat Masetty, open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list, Michael J. Ruhl, Sean Paul

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 748cd379065f..c6ecb3189ec5 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -938,8 +938,8 @@ static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo)
 	kfree(bo);
 }
 
-static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
-		size_t size)
+static struct a6xx_gmu_bo *
+a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, size_t size, uint64_t iova)
 {
 	struct a6xx_gmu_bo *bo;
 	int ret, count, i;
@@ -964,13 +964,13 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
 			goto err;
 	}
 
-	bo->iova = gmu->uncached_iova_base;
+	bo->iova = iova ?: gmu->uncached_iova_base;
 
 	for (i = 0; i < count; i++) {
 		ret = iommu_map(gmu->domain,
 			bo->iova + (PAGE_SIZE * i),
 			page_to_phys(bo->pages[i]), PAGE_SIZE,
-			IOMMU_READ | IOMMU_WRITE);
+			IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV);
 
 		if (ret) {
 			DRM_DEV_ERROR(gmu->dev, "Unable to map GMU buffer object\n");
@@ -990,7 +990,8 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
 		goto err;
 
 	/* Align future IOVA addresses on 1MB boundaries */
-	gmu->uncached_iova_base += ALIGN(size, SZ_1M);
+	if (!iova)
+		gmu->uncached_iova_base += ALIGN(size, SZ_1M);
 
 	return bo;
 
@@ -1331,12 +1332,12 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 		goto err_put_device;
 
 	/* Allocate memory for for the HFI queues */
-	gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K);
+	gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
 	if (IS_ERR(gmu->hfi))
 		goto err_memory;
 
 	/* Allocate memory for the GMU debug region */
-	gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K);
+	gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
 	if (IS_ERR(gmu->debug))
 		goto err_memory;
 
-- 
2.26.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 4/9] drm/msm/a6xx: HFI v2 for A640 and A650
       [not found] <20200420140313.7263-1-jonathan@marek.ca>
                   ` (2 preceding siblings ...)
  2020-04-20 14:03 ` [PATCH 3/9] drm/msm/a6xx: allow allocating GMU memory with a fixed address Jonathan Marek
@ 2020-04-20 14:03 ` Jonathan Marek
  2020-04-21 16:30   ` Jordan Crouse
  2020-04-20 14:03 ` [PATCH 5/9] drm/msm/a6xx: A640/A650 GMU firmware path Jonathan Marek
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 14:03 UTC (permalink / raw)
  To: freedreno
  Cc: David Airlie, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sharat Masetty, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Akhil P Oommen, Michael J. Ruhl, Sean Paul, open list

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c |  68 ++++++++++++---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h |   7 ++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c |   6 +-
 drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 117 ++++++++++++++++++++++++--
 drivers/gpu/drm/msm/adreno/a6xx_hfi.h |  50 ++++++++++-
 5 files changed, 224 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index c6ecb3189ec5..dc2d69837110 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -126,8 +126,6 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
 	if (ret)
 		dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
 
-	gmu->freq = gmu->gpu_freqs[index];
-
 	/*
 	 * Eventually we will want to scale the path vote with the frequency but
 	 * for now leave it at max so that the performance is nominal.
@@ -151,7 +149,12 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
 
 	gmu->current_perf_index = perf_index;
 
-	__a6xx_gmu_set_freq(gmu, perf_index);
+	if (gmu->legacy)
+		__a6xx_gmu_set_freq(gmu, perf_index);
+	else
+		a6xx_hfi_set_freq(gmu, perf_index);
+
+	gmu->freq = gmu->gpu_freqs[perf_index];
 }
 
 unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu)
@@ -231,19 +234,26 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
 
 	switch (state) {
 	case GMU_OOB_GPU_SET:
-		request = GMU_OOB_GPU_SET_REQUEST;
-		ack = GMU_OOB_GPU_SET_ACK;
+		if (gmu->legacy) {
+			request = GMU_OOB_GPU_SET_REQUEST;
+			ack = GMU_OOB_GPU_SET_ACK;
+		} else {
+			request = GMU_OOB_GPU_SET_REQUEST_NEW;
+			ack = GMU_OOB_GPU_SET_ACK_NEW;
+		}
 		name = "GPU_SET";
 		break;
 	case GMU_OOB_BOOT_SLUMBER:
 		request = GMU_OOB_BOOT_SLUMBER_REQUEST;
 		ack = GMU_OOB_BOOT_SLUMBER_ACK;
 		name = "BOOT_SLUMBER";
+		WARN_ON(!gmu->legacy);
 		break;
 	case GMU_OOB_DCVS_SET:
 		request = GMU_OOB_DCVS_REQUEST;
 		ack = GMU_OOB_DCVS_ACK;
 		name = "GPU_DCVS";
+		WARN_ON(!gmu->legacy);
 		break;
 	default:
 		return -EINVAL;
@@ -271,6 +281,13 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
 /* Clear a pending OOB state in the GMU */
 void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
 {
+	if (!gmu->legacy) {
+		WARN_ON(state != GMU_OOB_GPU_SET);
+		gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
+			1 << GMU_OOB_GPU_SET_CLEAR_NEW);
+		return;
+	}
+
 	switch (state) {
 	case GMU_OOB_GPU_SET:
 		gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
@@ -293,6 +310,9 @@ static int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
 	int ret;
 	u32 val;
 
+	if (!gmu->legacy)
+		return 0;
+
 	gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000);
 
 	ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, val,
@@ -312,6 +332,9 @@ static void a6xx_sptprac_disable(struct a6xx_gmu *gmu)
 	u32 val;
 	int ret;
 
+	if (!gmu->legacy)
+		return;
+
 	/* Make sure retention is on */
 	gmu_rmw(gmu, REG_A6XX_GPU_CC_GX_GDSCR, 0, (1 << 11));
 
@@ -355,6 +378,11 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
 	if (gmu->idle_level < GMU_IDLE_STATE_SPTP)
 		a6xx_sptprac_disable(gmu);
 
+	if (!gmu->legacy) {
+		ret = a6xx_hfi_send_prep_slumber(gmu);
+		goto out;
+	}
+
 	/* Tell the GMU to get ready to slumber */
 	gmu_write(gmu, REG_A6XX_GMU_BOOT_SLUMBER_OPTION, 1);
 
@@ -370,6 +398,7 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
 		}
 	}
 
+out:
 	/* Put fence into allow mode */
 	gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0);
 	return ret;
@@ -639,9 +668,11 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
 	if (ret)
 		return ret;
 
-	ret = a6xx_gmu_gfx_rail_on(gmu);
-	if (ret)
-		return ret;
+	if (gmu->legacy) {
+		ret = a6xx_gmu_gfx_rail_on(gmu);
+		if (ret)
+			return ret;
+	}
 
 	/* Enable SPTP_PC if the CPU is responsible for it */
 	if (gmu->idle_level < GMU_IDLE_STATE_SPTP) {
@@ -760,7 +791,10 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
 	enable_irq(gmu->hfi_irq);
 
 	/* Set the GPU to the current freq */
-	__a6xx_gmu_set_freq(gmu, gmu->current_perf_index);
+	if (gmu->legacy)
+		__a6xx_gmu_set_freq(gmu, gmu->current_perf_index);
+	else
+		a6xx_hfi_set_freq(gmu, gmu->current_perf_index);
 
 	/*
 	 * "enable" the GX power domain which won't actually do anything but it
@@ -1305,6 +1339,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
 
 int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 {
+	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
 	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
 	struct platform_device *pdev = of_find_device_by_node(node);
 	int ret;
@@ -1331,16 +1366,21 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	if (ret)
 		goto err_put_device;
 
+	if (!adreno_is_a640(adreno_gpu) && !adreno_is_a650(adreno_gpu)) {
+		/* HFI v1, no sptprac */
+		gmu->legacy = true;
+
+		/* Allocate memory for the GMU debug region */
+		gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
+		if (IS_ERR(gmu->debug))
+			goto err_memory;
+	}
+
 	/* Allocate memory for for the HFI queues */
 	gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
 	if (IS_ERR(gmu->hfi))
 		goto err_memory;
 
-	/* Allocate memory for the GMU debug region */
-	gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
-	if (IS_ERR(gmu->debug))
-		goto err_memory;
-
 	/* Map the GMU registers */
 	gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
 	if (IS_ERR(gmu->mmio))
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 2af91ed7ed0c..781714ffaa91 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -80,6 +80,7 @@ struct a6xx_gmu {
 
 	bool initialized;
 	bool hung;
+	bool legacy; /* a618 or a630 */
 };
 
 static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
@@ -160,10 +161,16 @@ enum a6xx_gmu_oob_state {
 #define GMU_OOB_GPU_SET_ACK	24
 #define GMU_OOB_GPU_SET_CLEAR	24
 
+#define GMU_OOB_GPU_SET_REQUEST_NEW	30
+#define GMU_OOB_GPU_SET_ACK_NEW		31
+#define GMU_OOB_GPU_SET_CLEAR_NEW	31
+
 
 void a6xx_hfi_init(struct a6xx_gmu *gmu);
 int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
 void a6xx_hfi_stop(struct a6xx_gmu *gmu);
+int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu);
+int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index);
 
 bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
 bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index 68af24150de5..a860d4970e10 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -566,8 +566,10 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
 	 */
 	a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
 
-	/* Take the GMU out of its special boot mode */
-	a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
+	if (a6xx_gpu->gmu.legacy) {
+		/* Take the GMU out of its special boot mode */
+		a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
+	}
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index e450e0b97211..3d4b142d8fb3 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -17,10 +17,14 @@ static const char * const a6xx_hfi_msg_id[] = {
 	HFI_MSG_ID(HFI_H2F_MSG_BW_TABLE),
 	HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),
 	HFI_MSG_ID(HFI_H2F_MSG_TEST),
+	HFI_MSG_ID(HFI_H2F_MSG_START),
+	HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START),
+	HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE),
+	HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER),
 };
 
-static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data,
-		u32 dwords)
+static int a6xx_hfi_queue_read(struct a6xx_gmu *gmu,
+	struct a6xx_hfi_queue *queue, u32 *data, u32 dwords)
 {
 	struct a6xx_hfi_queue_header *header = queue->header;
 	u32 i, hdr, index = header->read_index;
@@ -48,6 +52,9 @@ static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data,
 		index = (index + 1) % header->size;
 	}
 
+	if (!gmu->legacy)
+		index = ALIGN(index, 4) % header->size;
+
 	header->read_index = index;
 	return HFI_HEADER_SIZE(hdr);
 }
@@ -73,6 +80,12 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu,
 		index = (index + 1) % header->size;
 	}
 
+	/* Cookify any non used data at the end of the write buffer */
+	if (!gmu->legacy) {
+		for (; index % 4; index = (index + 1) % header->size)
+			queue->data[index] = 0xfafafafa;
+	}
+
 	header->write_index = index;
 	spin_unlock(&queue->lock);
 
@@ -106,7 +119,7 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum,
 		struct a6xx_hfi_msg_response resp;
 
 		/* Get the next packet */
-		ret = a6xx_hfi_queue_read(queue, (u32 *) &resp,
+		ret = a6xx_hfi_queue_read(gmu, queue, (u32 *) &resp,
 			sizeof(resp) >> 2);
 
 		/* If the queue is empty our response never made it */
@@ -195,6 +208,28 @@ static int a6xx_hfi_get_fw_version(struct a6xx_gmu *gmu, u32 *version)
 		version, sizeof(*version));
 }
 
+static int a6xx_hfi_send_perf_table_v1(struct a6xx_gmu *gmu)
+{
+	struct a6xx_hfi_msg_perf_table_v1 msg = { 0 };
+	int i;
+
+	msg.num_gpu_levels = gmu->nr_gpu_freqs;
+	msg.num_gmu_levels = gmu->nr_gmu_freqs;
+
+	for (i = 0; i < gmu->nr_gpu_freqs; i++) {
+		msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
+		msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
+	}
+
+	for (i = 0; i < gmu->nr_gmu_freqs; i++) {
+		msg.cx_votes[i].vote = gmu->cx_arc_votes[i];
+		msg.cx_votes[i].freq = gmu->gmu_freqs[i] / 1000;
+	}
+
+	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PERF_TABLE, &msg, sizeof(msg),
+		NULL, 0);
+}
+
 static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
 {
 	struct a6xx_hfi_msg_perf_table msg = { 0 };
@@ -205,6 +240,7 @@ static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
 
 	for (i = 0; i < gmu->nr_gpu_freqs; i++) {
 		msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
+		msg.gx_votes[i].acd = 0xffffffff;
 		msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
 	}
 
@@ -306,7 +342,45 @@ static int a6xx_hfi_send_test(struct a6xx_gmu *gmu)
 		NULL, 0);
 }
 
-int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
+int a6xx_hfi_send_start(struct a6xx_gmu *gmu)
+{
+	struct a6xx_hfi_msg_start msg = { 0 };
+
+	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_START, &msg, sizeof(msg),
+		NULL, 0);
+}
+
+int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu)
+{
+	struct a6xx_hfi_msg_core_fw_start msg = { 0 };
+
+	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_CORE_FW_START, &msg,
+		sizeof(msg), NULL, 0);
+}
+
+int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index)
+{
+	struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 };
+
+	msg.ack_type = 1; /* blocking */
+	msg.freq = index;
+	msg.bw = 0; /* TODO: bus scaling */
+
+	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg,
+		sizeof(msg), NULL, 0);
+}
+
+int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu)
+{
+	struct a6xx_hfi_prep_slumber_cmd msg = { 0 };
+
+	/* TODO: should freq and bw fields be non-zero ? */
+
+	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PREPARE_SLUMBER, &msg,
+		sizeof(msg), NULL, 0);
+}
+
+static int a6xx_hfi_start_v1(struct a6xx_gmu *gmu, int boot_state)
 {
 	int ret;
 
@@ -324,7 +398,7 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
 	 * the GMU firmware
 	 */
 
-	ret = a6xx_hfi_send_perf_table(gmu);
+	ret = a6xx_hfi_send_perf_table_v1(gmu);
 	if (ret)
 		return ret;
 
@@ -341,6 +415,37 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
 	return 0;
 }
 
+int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
+{
+	int ret;
+
+	if (gmu->legacy)
+		return a6xx_hfi_start_v1(gmu, boot_state);
+
+
+	ret = a6xx_hfi_send_perf_table(gmu);
+	if (ret)
+		return ret;
+
+	ret = a6xx_hfi_send_bw_table(gmu);
+	if (ret)
+		return ret;
+
+	ret = a6xx_hfi_send_core_fw_start(gmu);
+	if (ret)
+		return ret;
+
+	/*
+	 * Downstream driver sends this in its "a6xx_hw_init" equivalent,
+	 * but seems to be no harm in sending it here
+	 */
+	ret = a6xx_hfi_send_start(gmu);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 void a6xx_hfi_stop(struct a6xx_gmu *gmu)
 {
 	int i;
@@ -415,5 +520,5 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu)
 	/* GMU response queue */
 	offset += SZ_4K;
 	a6xx_hfi_queue_init(&gmu->queues[1], &headers[1], hfi->virt + offset,
-		hfi->iova + offset, 4);
+		hfi->iova + offset, gmu->legacy ? 4 : 1);
 }
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
index 60d1319fa44f..2bd670ca42d6 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
@@ -51,7 +51,8 @@ struct a6xx_hfi_queue {
 /* HFI message types */
 
 #define HFI_MSG_CMD 0
-#define HFI_MSG_ACK 2
+#define HFI_MSG_ACK 1
+#define HFI_MSG_ACK_V1 2
 
 #define HFI_F2H_MSG_ACK 126
 
@@ -94,7 +95,13 @@ struct perf_level {
 	u32 freq;
 };
 
-struct a6xx_hfi_msg_perf_table {
+struct perf_gx_level {
+	u32 vote;
+	u32 acd;
+	u32 freq;
+};
+
+struct a6xx_hfi_msg_perf_table_v1 {
 	u32 header;
 	u32 num_gpu_levels;
 	u32 num_gmu_levels;
@@ -103,6 +110,15 @@ struct a6xx_hfi_msg_perf_table {
 	struct perf_level cx_votes[4];
 };
 
+struct a6xx_hfi_msg_perf_table {
+	u32 header;
+	u32 num_gpu_levels;
+	u32 num_gmu_levels;
+
+	struct perf_gx_level gx_votes[16];
+	struct perf_level cx_votes[4];
+};
+
 #define HFI_H2F_MSG_BW_TABLE 3
 
 struct a6xx_hfi_msg_bw_table {
@@ -124,4 +140,34 @@ struct a6xx_hfi_msg_test {
 	u32 header;
 };
 
+#define HFI_H2F_MSG_START 10
+
+struct a6xx_hfi_msg_start {
+	u32 header;
+};
+
+#define HFI_H2F_MSG_CORE_FW_START 14
+
+struct a6xx_hfi_msg_core_fw_start {
+	u32 header;
+	u32 handle;
+};
+
+#define HFI_H2F_MSG_GX_BW_PERF_VOTE 30
+
+struct a6xx_hfi_gx_bw_perf_vote_cmd {
+	u32 header;
+	u32 ack_type;
+	u32 freq;
+	u32 bw;
+};
+
+#define HFI_H2F_MSG_PREPARE_SLUMBER 33
+
+struct a6xx_hfi_prep_slumber_cmd {
+	u32 header;
+	u32 bw;
+	u32 freq;
+};
+
 #endif
-- 
2.26.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 5/9] drm/msm/a6xx: A640/A650 GMU firmware path
       [not found] <20200420140313.7263-1-jonathan@marek.ca>
                   ` (3 preceding siblings ...)
  2020-04-20 14:03 ` [PATCH 4/9] drm/msm/a6xx: HFI v2 for A640 and A650 Jonathan Marek
@ 2020-04-20 14:03 ` Jonathan Marek
  2020-04-20 14:03 ` [PATCH 6/9] drm/msm/a6xx: add support for A650 gmu rscc registers Jonathan Marek
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 14:03 UTC (permalink / raw)
  To: freedreno
  Cc: David Airlie, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sharat Masetty, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Stephen Boyd, Michael J. Ruhl, Sean Paul, open list

Newer GPUs have different gmu firmware path.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c     | 136 +++++++++++++++++++---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h     |  11 ++
 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h |   6 +
 3 files changed, 138 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index dc2d69837110..6dffd1095a24 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -570,6 +570,8 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu)
 {
 	/* Disable GMU WB/RB buffer */
 	gmu_write(gmu, REG_A6XX_GMU_SYS_BUS_CONFIG, 0x1);
+	gmu_write(gmu, REG_A6XX_GMU_ICACHE_CONFIG, 0x1);
+	gmu_write(gmu, REG_A6XX_GMU_DCACHE_CONFIG, 0x1);
 
 	gmu_write(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0x9c40400);
 
@@ -599,14 +601,91 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu)
 		A6XX_GMU_RPMH_CTRL_GFX_VOTE_ENABLE);
 }
 
+static int in_range(u32 addr, u32 start, u32 size)
+{
+	return addr >= start && addr < start + size;
+}
+
+static int a6xx_gmu_fw_load(struct a6xx_gmu *gmu)
+{
+	struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
+	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
+	const struct firmware *fw_image = adreno_gpu->fw[ADRENO_FW_GMU];
+	const struct block_header {
+		u32 addr;
+		u32 size;
+		u32 type;
+		u32 value;
+		u32 data[];
+	} *blk;
+	struct a6xx_gmu_bo *mem;
+	u32 reg;
+
+	u32 itcm_base = 0x00000000;
+	u32 dtcm_base = 0x00040000;
+
+	if (adreno_is_a650(adreno_gpu))
+		dtcm_base = 0x10004000;
+
+	if (gmu->legacy) {
+		/* Sanity check the size of the firmware that was loaded */
+		if (fw_image->size > 0x8000) {
+			DRM_DEV_ERROR(gmu->dev,
+				"GMU firmware is bigger than the available region\n");
+			return -EINVAL;
+		}
+
+		gmu_write_bulk(gmu, REG_A6XX_GMU_CM3_ITCM_START,
+			       (u32*) fw_image->data, fw_image->size >> 2);
+		return 0;
+	}
+
+
+	for (blk = (const struct block_header *) fw_image->data;
+	     (const u8*) blk < fw_image->data + fw_image->size;
+	     blk = (const struct block_header *) &blk->data[blk->size >> 2]) {
+		if (blk->size == 0)
+			continue;
+
+		reg = 0;
+		mem = NULL;
+
+		if (in_range(blk->addr, itcm_base, SZ_16K))
+			reg = REG_A6XX_GMU_CM3_ITCM_START + ((blk->addr - itcm_base) >> 2);
+		else if (in_range(blk->addr, dtcm_base, SZ_16K))
+			reg = REG_A6XX_GMU_CM3_DTCM_START + ((blk->addr - dtcm_base) >> 2);
+		else if (in_range(blk->addr, gmu->icache->iova, gmu->icache->size))
+			mem = gmu->icache;
+		else if (in_range(blk->addr, gmu->dcache->iova, gmu->dcache->size))
+			mem = gmu->dcache;
+		else if (in_range(blk->addr, gmu->dummy->iova, gmu->dummy->size))
+			mem = gmu->dummy;
+		else {
+			DRM_DEV_ERROR(gmu->dev,
+				"failed to match fw block (addr=%.8x size=%d data[0]=%.8x)\n",
+				blk->addr, blk->size, blk->data[0]);
+		}
+
+		if (reg)
+			gmu_write_bulk(gmu, reg, blk->data, blk->size >> 2);
+
+		if (mem)
+			memcpy(mem->virt + blk->addr - mem->iova, blk->data, blk->size);
+	}
+
+	return 0;
+}
+
 static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
 {
 	static bool rpmh_init;
 	struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
 	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
-	int i, ret;
+	int ret;
 	u32 chipid;
-	u32 *image;
+
+	if (adreno_is_a650(adreno_gpu))
+		gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF, 1);
 
 	if (state == GMU_WARM_BOOT) {
 		ret = a6xx_rpmh_start(gmu);
@@ -617,13 +696,6 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
 			"GMU firmware is not loaded\n"))
 			return -ENOENT;
 
-		/* Sanity check the size of the firmware that was loaded */
-		if (adreno_gpu->fw[ADRENO_FW_GMU]->size > 0x8000) {
-			DRM_DEV_ERROR(gmu->dev,
-				"GMU firmware is bigger than the available region\n");
-			return -EINVAL;
-		}
-
 		/* Turn on register retention */
 		gmu_write(gmu, REG_A6XX_GMU_GENERAL_7, 1);
 
@@ -637,11 +709,9 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
 				return ret;
 		}
 
-		image = (u32 *) adreno_gpu->fw[ADRENO_FW_GMU]->data;
-
-		for (i = 0; i < adreno_gpu->fw[ADRENO_FW_GMU]->size >> 2; i++)
-			gmu_write(gmu, REG_A6XX_GMU_CM3_ITCM_START + i,
-				image[i]);
+		ret = a6xx_gmu_fw_load(gmu);
+		if (ret)
+			return ret;
 	}
 
 	gmu_write(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, 0);
@@ -768,12 +838,20 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
 	/* Enable the GMU interrupt */
 	gmu_write(gmu, REG_A6XX_GMU_AO_HOST_INTERRUPT_CLR, ~0);
 	gmu_write(gmu, REG_A6XX_GMU_AO_HOST_INTERRUPT_MASK, ~A6XX_GMU_IRQ_MASK);
+
 	enable_irq(gmu->gmu_irq);
 
 	/* Check to see if we are doing a cold or warm boot */
 	status = gmu_read(gmu, REG_A6XX_GMU_GENERAL_7) == 1 ?
 		GMU_WARM_BOOT : GMU_COLD_BOOT;
 
+	/*
+	 * Warm boot path does not work on newer GPUs
+	 * Presumably this is because icache/dcache regions must be restored
+	 */
+	if (!gmu->legacy)
+		status = GMU_COLD_BOOT;
+
 	ret = a6xx_gmu_fw_start(gmu, status);
 	if (ret)
 		goto out;
@@ -1322,6 +1400,10 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
 	iounmap(gmu->mmio);
 	gmu->mmio = NULL;
 
+	a6xx_gmu_memory_free(gmu, gmu->icache);
+	a6xx_gmu_memory_free(gmu, gmu->dcache);
+	a6xx_gmu_memory_free(gmu, gmu->dummy);
+	a6xx_gmu_memory_free(gmu, gmu->debug);
 	a6xx_gmu_memory_free(gmu, gmu->hfi);
 
 	iommu_detach_device(gmu->domain, gmu->dev);
@@ -1366,7 +1448,27 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	if (ret)
 		goto err_put_device;
 
-	if (!adreno_is_a640(adreno_gpu) && !adreno_is_a650(adreno_gpu)) {
+	/*
+	 * Allocate memory for the GMU dummy page
+	 * note: allocated first so iova is 0x60000000
+	 */
+	gmu->dummy = a6xx_gmu_memory_alloc(gmu, SZ_4K, 0);
+	if (IS_ERR(gmu->dummy))
+		goto err_memory;
+
+	if (adreno_is_a650(adreno_gpu)) {
+		gmu->icache = a6xx_gmu_memory_alloc(gmu, SZ_16M - SZ_16K, 0x04000);
+		if (IS_ERR(gmu->icache))
+			goto err_memory;
+	} else if (adreno_is_a640(adreno_gpu)) {
+		gmu->icache = a6xx_gmu_memory_alloc(gmu, SZ_256K - SZ_16K, 0x04000);
+		if (IS_ERR(gmu->icache))
+			goto err_memory;
+
+		gmu->dcache = a6xx_gmu_memory_alloc(gmu, SZ_256K - SZ_16K, 0x44000);
+		if (IS_ERR(gmu->dcache))
+			goto err_memory;
+	} else {
 		/* HFI v1, no sptprac */
 		gmu->legacy = true;
 
@@ -1414,6 +1516,10 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	free_irq(gmu->gmu_irq, gmu);
 	free_irq(gmu->hfi_irq, gmu);
 err_memory:
+	a6xx_gmu_memory_free(gmu, gmu->icache);
+	a6xx_gmu_memory_free(gmu, gmu->dcache);
+	a6xx_gmu_memory_free(gmu, gmu->dummy);
+	a6xx_gmu_memory_free(gmu, gmu->debug);
 	a6xx_gmu_memory_free(gmu, gmu->hfi);
 
 	if (gmu->domain) {
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index 781714ffaa91..ff5d9c61e487 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -58,6 +58,9 @@ struct a6xx_gmu {
 
 	struct a6xx_gmu_bo *hfi;
 	struct a6xx_gmu_bo *debug;
+	struct a6xx_gmu_bo *icache;
+	struct a6xx_gmu_bo *dcache;
+	struct a6xx_gmu_bo *dummy;
 
 	int nr_clocks;
 	struct clk_bulk_data *clocks;
@@ -93,6 +96,14 @@ static inline void gmu_write(struct a6xx_gmu *gmu, u32 offset, u32 value)
 	return msm_writel(value, gmu->mmio + (offset << 2));
 }
 
+static inline void
+gmu_write_bulk(struct a6xx_gmu *gmu, u32 offset, const u32 *data, u32 size)
+{
+	int i;
+	for (i = 0; i < size; i++)
+		gmu_write(gmu, offset + i, data[i]);
+}
+
 static inline void gmu_rmw(struct a6xx_gmu *gmu, u32 reg, u32 mask, u32 or)
 {
 	u32 val = gmu_read(gmu, reg);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
index 1cc1c135236b..eb2cd41dae6e 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
@@ -101,6 +101,10 @@ static inline uint32_t A6XX_HFI_IRQ_OOB_MASK(uint32_t val)
 
 #define REG_A6XX_GMU_DCVS_RETURN				0x000023ff
 
+#define REG_A6XX_GMU_ICACHE_CONFIG				0x00004c00
+
+#define REG_A6XX_GMU_DCACHE_CONFIG				0x00004c01
+
 #define REG_A6XX_GMU_SYS_BUS_CONFIG				0x00004c0f
 
 #define REG_A6XX_GMU_CM3_SYSRESET				0x00005000
@@ -199,6 +203,8 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val)
 
 #define REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE		0x000050ec
 
+#define REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF			0x000050f0
+
 #define REG_A6XX_GMU_BOOT_KMD_LM_HANDSHAKE			0x000051f0
 
 #define REG_A6XX_GMU_LLM_GLM_SLEEP_CTRL				0x00005157
-- 
2.26.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 6/9] drm/msm/a6xx: add support for A650 gmu rscc registers
       [not found] <20200420140313.7263-1-jonathan@marek.ca>
                   ` (4 preceding siblings ...)
  2020-04-20 14:03 ` [PATCH 5/9] drm/msm/a6xx: A640/A650 GMU firmware path Jonathan Marek
@ 2020-04-20 14:03 ` Jonathan Marek
  2020-04-20 14:03 ` [PATCH 7/9] drm/msm/a6xx: gmu_pdc register values for A640 and A650 Jonathan Marek
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 14:03 UTC (permalink / raw)
  To: freedreno
  Cc: David Airlie, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sharat Masetty, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Stephen Boyd, Michael J. Ruhl, Sean Paul, open list

Some of the RSCC registers on A650 are in a separate region.

Note this also changes the address of these registers:

RSCC_TCS1_DRV0_STATUS
RSCC_TCS2_DRV0_STATUS
RSCC_TCS3_DRV0_STATUS

Based on the values in msm-4.14 and msm-4.19 kernels.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c     | 68 +++++++++++++++--------
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h     | 10 ++++
 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h | 38 ++++++-------
 3 files changed, 74 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 6dffd1095a24..3e51939eb867 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -420,7 +420,7 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu)
 		return ret;
 	}
 
-	ret = gmu_poll_timeout(gmu, REG_A6XX_RSCC_SEQ_BUSY_DRV0, val,
+	ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_SEQ_BUSY_DRV0, val,
 		!val, 100, 10000);
 
 	if (ret) {
@@ -446,7 +446,7 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
 
 	gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1);
 
-	ret = gmu_poll_timeout(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
+	ret = gmu_poll_timeout_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
 		val, val & (1 << 16), 100, 10000);
 	if (ret)
 		DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
@@ -474,27 +474,35 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
 		goto err;
 
 	/* Disable SDE clock gating */
-	gmu_write(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));
+	gmu_write_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));
 
 	/* Setup RSC PDC handshake for sleep and wakeup */
-	gmu_write(gmu, REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1);
-	gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0);
-	gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0);
-	gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0);
-	gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0);
-	gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, 0x80000000);
-	gmu_write(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0);
-	gmu_write(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0);
-	gmu_write(gmu, REG_A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520);
-	gmu_write(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510);
-	gmu_write(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0, 1);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA, 0);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR, 0);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 2, 0);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 2, 0);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA + 4, 0x80000000);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR + 4, 0);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_OVERRIDE_START_ADDR, 0);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_SEQ_START_ADDR, 0x4520);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_LO, 0x4510);
+	gmu_write_rscc(gmu, REG_A6XX_RSCC_PDC_MATCH_VALUE_HI, 0x4514);
 
 	/* Load RSC sequencer uCode for sleep and wakeup */
-	gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xa7a506a0);
-	gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xa1e6a6e7);
-	gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e081e1);
-	gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xe9a982e2);
-	gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020e8a8);
+	if (adreno_is_a650(adreno_gpu)) {
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xeaaae5a0);
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xe1a1ebab);
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e0a581);
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xecac82e2);
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020edad);
+	} else {
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0, 0xa7a506a0);
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 1, 0xa1e6a6e7);
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 2, 0xa2e081e1);
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 3, 0xe9a982e2);
+		gmu_write_rscc(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020e8a8);
+	}
 
 	/* Load PDC sequencer uCode for power up and power down sequence */
 	pdc_write(seqptr, REG_A6XX_PDC_GPU_SEQ_MEM_0, 0xfebea1e1);
@@ -783,13 +791,13 @@ static void a6xx_gmu_rpmh_off(struct a6xx_gmu *gmu)
 	u32 val;
 
 	/* Make sure there are no outstanding RPMh votes */
-	gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS0_DRV0_STATUS, val,
+	gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS0_DRV0_STATUS, val,
 		(val & 1), 100, 10000);
-	gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS1_DRV0_STATUS, val,
+	gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS1_DRV0_STATUS, val,
 		(val & 1), 100, 10000);
-	gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS2_DRV0_STATUS, val,
+	gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS2_DRV0_STATUS, val,
 		(val & 1), 100, 10000);
-	gmu_poll_timeout(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS, val,
+	gmu_poll_timeout_rscc(gmu, REG_A6XX_RSCC_TCS3_DRV0_STATUS, val,
 		(val & 1), 100, 1000);
 }
 
@@ -1385,6 +1393,7 @@ static int a6xx_gmu_get_irq(struct a6xx_gmu *gmu, struct platform_device *pdev,
 
 void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
 {
+	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
 	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
 
 	if (!gmu->initialized)
@@ -1398,7 +1407,10 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
 	}
 
 	iounmap(gmu->mmio);
+	if (adreno_is_a650(adreno_gpu))
+		iounmap(gmu->rscc);
 	gmu->mmio = NULL;
+	gmu->rscc = NULL;
 
 	a6xx_gmu_memory_free(gmu, gmu->icache);
 	a6xx_gmu_memory_free(gmu, gmu->dcache);
@@ -1488,6 +1500,14 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	if (IS_ERR(gmu->mmio))
 		goto err_memory;
 
+	if (adreno_is_a650(adreno_gpu)) {
+		gmu->rscc = a6xx_gmu_get_mmio(pdev, "rscc");
+		if (IS_ERR(gmu->rscc))
+			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);
@@ -1513,6 +1533,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 
 err_mmio:
 	iounmap(gmu->mmio);
+	if (adreno_is_a650(adreno_gpu))
+		iounmap(gmu->rscc);
 	free_irq(gmu->gmu_irq, gmu);
 	free_irq(gmu->hfi_irq, gmu);
 err_memory:
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index ff5d9c61e487..abd425ca6682 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -45,6 +45,7 @@ struct a6xx_gmu {
 	struct device *dev;
 
 	void * __iomem mmio;
+	void * __iomem rscc;
 
 	int hfi_irq;
 	int gmu_irq;
@@ -127,6 +128,15 @@ static inline u64 gmu_read64(struct a6xx_gmu *gmu, u32 lo, u32 hi)
 	readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \
 		interval, timeout)
 
+static inline void gmu_write_rscc(struct a6xx_gmu *gmu, u32 offset, u32 value)
+{
+	return msm_writel(value, gmu->rscc + (offset << 2));
+}
+
+#define gmu_poll_timeout_rscc(gmu, addr, val, cond, interval, timeout) \
+	readl_poll_timeout((gmu)->rscc + ((addr) << 2), val, cond, \
+		interval, timeout)
+
 /*
  * These are the available OOB (out of band requests) to the GMU where "out of
  * band" means that the CPU talks to the GMU directly and not through HFI.
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
index eb2cd41dae6e..b4357ea550ec 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
@@ -336,8 +336,6 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val)
 
 #define REG_A6XX_GMU_AO_SPARE_CNTL				0x00009316
 
-#define REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0			0x00008c04
-
 #define REG_A6XX_GMU_RSCC_CONTROL_REQ				0x00009307
 
 #define REG_A6XX_GMU_RSCC_CONTROL_ACK				0x00009308
@@ -350,39 +348,41 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val)
 
 #define REG_A6XX_GPU_CC_GX_DOMAIN_MISC				0x00009d42
 
-#define REG_A6XX_RSCC_PDC_SEQ_START_ADDR			0x00008c08
+#define REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0			0x00000004
+
+#define REG_A6XX_RSCC_PDC_SEQ_START_ADDR			0x00000008
 
-#define REG_A6XX_RSCC_PDC_MATCH_VALUE_LO			0x00008c09
+#define REG_A6XX_RSCC_PDC_MATCH_VALUE_LO			0x00000009
 
-#define REG_A6XX_RSCC_PDC_MATCH_VALUE_HI			0x00008c0a
+#define REG_A6XX_RSCC_PDC_MATCH_VALUE_HI			0x0000000a
 
-#define REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0				0x00008c0b
+#define REG_A6XX_RSCC_PDC_SLAVE_ID_DRV0				0x0000000b
 
-#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR			0x00008c0d
+#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_ADDR			0x0000000d
 
-#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA			0x00008c0e
+#define REG_A6XX_RSCC_HIDDEN_TCS_CMD0_DATA			0x0000000e
 
-#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0		0x00008c82
+#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_L_DRV0		0x00000082
 
-#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0		0x00008c83
+#define REG_A6XX_RSCC_TIMESTAMP_UNIT0_TIMESTAMP_H_DRV0		0x00000083
 
-#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0			0x00008c89
+#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0			0x00000089
 
-#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0		0x00008c8c
+#define REG_A6XX_RSCC_TIMESTAMP_UNIT1_OUTPUT_DRV0		0x0000008c
 
-#define REG_A6XX_RSCC_OVERRIDE_START_ADDR			0x00008d00
+#define REG_A6XX_RSCC_OVERRIDE_START_ADDR			0x00000100
 
-#define REG_A6XX_RSCC_SEQ_BUSY_DRV0				0x00008d01
+#define REG_A6XX_RSCC_SEQ_BUSY_DRV0				0x00000101
 
-#define REG_A6XX_RSCC_SEQ_MEM_0_DRV0				0x00008d80
+#define REG_A6XX_RSCC_SEQ_MEM_0_DRV0				0x00000180
 
-#define REG_A6XX_RSCC_TCS0_DRV0_STATUS				0x00008f46
+#define REG_A6XX_RSCC_TCS0_DRV0_STATUS				0x00000346
 
-#define REG_A6XX_RSCC_TCS1_DRV0_STATUS				0x000090ae
+#define REG_A6XX_RSCC_TCS1_DRV0_STATUS				0x000003ee
 
-#define REG_A6XX_RSCC_TCS2_DRV0_STATUS				0x00009216
+#define REG_A6XX_RSCC_TCS2_DRV0_STATUS				0x00000496
 
-#define REG_A6XX_RSCC_TCS3_DRV0_STATUS				0x0000937e
+#define REG_A6XX_RSCC_TCS3_DRV0_STATUS				0x0000053e
 
 
 #endif /* A6XX_GMU_XML */
-- 
2.26.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 7/9] drm/msm/a6xx: gmu_pdc register values for A640 and A650
       [not found] <20200420140313.7263-1-jonathan@marek.ca>
                   ` (5 preceding siblings ...)
  2020-04-20 14:03 ` [PATCH 6/9] drm/msm/a6xx: add support for A650 gmu rscc registers Jonathan Marek
@ 2020-04-20 14:03 ` Jonathan Marek
  2020-04-21 16:34   ` Jordan Crouse
  2020-04-20 14:03 ` [PATCH 8/9] drm/msm/a6xx: enable GMU log Jonathan Marek
  2020-04-20 14:03 ` [PATCH 9/9] drm/msm/a6xx: update a6xx_hw_init for A640 and A650 Jonathan Marek
  8 siblings, 1 reply; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 14:03 UTC (permalink / raw)
  To: freedreno
  Cc: David Airlie, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sharat Masetty, open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list, Sean Paul

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index 3e51939eb867..b583bf6e293b 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -469,10 +469,18 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
 	struct platform_device *pdev = to_platform_device(gmu->dev);
 	void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc");
 	void __iomem *seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq");
+	uint32_t pdc_address_offset;
 
 	if (!pdcptr || !seqptr)
 		goto err;
 
+	if (adreno_is_a618(adreno_gpu) || adreno_is_a640(adreno_gpu))
+		pdc_address_offset = 0x30090;
+	else if (adreno_is_a650(adreno_gpu))
+		pdc_address_offset = 0x300a0;
+	else
+		pdc_address_offset = 0x30080;
+
 	/* Disable SDE clock gating */
 	gmu_write_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));
 
@@ -523,10 +531,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
 	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 4, 0x0);
 
 	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID + 8, 0x10108);
-	if (adreno_is_a618(adreno_gpu))
-		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30090);
-	else
-		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30080);
+	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, pdc_address_offset);
 	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 8, 0x0);
 
 	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD_ENABLE_BANK, 7);
@@ -538,17 +543,12 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
 
 	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 4, 0x10108);
 	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 4, 0x30000);
-	if (adreno_is_a618(adreno_gpu))
+	if (adreno_is_a618(adreno_gpu) || adreno_is_a650(adreno_gpu))
 		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x2);
 	else
 		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x3);
-
-
 	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 8, 0x10108);
-	if (adreno_is_a618(adreno_gpu))
-		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30090);
-	else
-		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30080);
+	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, pdc_address_offset);
 	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 8, 0x3);
 
 	/* Setup GPU PDC */
-- 
2.26.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 8/9] drm/msm/a6xx: enable GMU log
       [not found] <20200420140313.7263-1-jonathan@marek.ca>
                   ` (6 preceding siblings ...)
  2020-04-20 14:03 ` [PATCH 7/9] drm/msm/a6xx: gmu_pdc register values for A640 and A650 Jonathan Marek
@ 2020-04-20 14:03 ` Jonathan Marek
  2020-04-21 16:38   ` [Freedreno] " Jordan Crouse
  2020-04-20 14:03 ` [PATCH 9/9] drm/msm/a6xx: update a6xx_hw_init for A640 and A650 Jonathan Marek
  8 siblings, 1 reply; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 14:03 UTC (permalink / raw)
  To: freedreno
  Cc: David Airlie, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sharat Masetty, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Stephen Boyd, Michael J. Ruhl, Sean Paul, open list

This is required for a650 to work.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
---
 drivers/gpu/drm/msm/adreno/a6xx_gmu.c     | 16 ++++++++++++++++
 drivers/gpu/drm/msm/adreno/a6xx_gmu.h     |  1 +
 drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h |  4 ++++
 3 files changed, 21 insertions(+)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index b583bf6e293b..1cdb7c832b87 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -198,6 +198,12 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
 	u32 val;
 
 	gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);
+
+	/* Set the log wptr index
+	 * note: downstream saves the value in poweroff and restores it here
+	 */
+	gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, 0);
+
 	gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0);
 
 	ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, val,
@@ -739,6 +745,9 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
 
 	gmu_write(gmu, REG_A6XX_GMU_HFI_SFR_ADDR, chipid);
 
+	gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG,
+		  gmu->log->iova | (gmu->log->size / SZ_4K - 1));
+
 	/* Set up the lowest idle level on the GMU */
 	a6xx_gmu_power_config(gmu);
 
@@ -1416,6 +1425,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
 	a6xx_gmu_memory_free(gmu, gmu->dcache);
 	a6xx_gmu_memory_free(gmu, gmu->dummy);
 	a6xx_gmu_memory_free(gmu, gmu->debug);
+	a6xx_gmu_memory_free(gmu, gmu->log);
 	a6xx_gmu_memory_free(gmu, gmu->hfi);
 
 	iommu_detach_device(gmu->domain, gmu->dev);
@@ -1495,6 +1505,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	if (IS_ERR(gmu->hfi))
 		goto err_memory;
 
+	/* Allocate memory for the GMU log region */
+	gmu->log = a6xx_gmu_memory_alloc(gmu, SZ_4K, 0);
+	if (IS_ERR(gmu->log))
+		goto err_memory;
+
 	/* Map the GMU registers */
 	gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
 	if (IS_ERR(gmu->mmio))
@@ -1542,6 +1557,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
 	a6xx_gmu_memory_free(gmu, gmu->dcache);
 	a6xx_gmu_memory_free(gmu, gmu->dummy);
 	a6xx_gmu_memory_free(gmu, gmu->debug);
+	a6xx_gmu_memory_free(gmu, gmu->log);
 	a6xx_gmu_memory_free(gmu, gmu->hfi);
 
 	if (gmu->domain) {
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index abd425ca6682..589b9b0c348e 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -59,6 +59,7 @@ struct a6xx_gmu {
 
 	struct a6xx_gmu_bo *hfi;
 	struct a6xx_gmu_bo *debug;
+	struct a6xx_gmu_bo *log;
 	struct a6xx_gmu_bo *icache;
 	struct a6xx_gmu_bo *dcache;
 	struct a6xx_gmu_bo *dummy;
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
index b4357ea550ec..176ae94d9fe6 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
@@ -205,6 +205,10 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val)
 
 #define REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF			0x000050f0
 
+#define REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG			0x00005100
+
+#define REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP			0x00005101
+
 #define REG_A6XX_GMU_BOOT_KMD_LM_HANDSHAKE			0x000051f0
 
 #define REG_A6XX_GMU_LLM_GLM_SLEEP_CTRL				0x00005157
-- 
2.26.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 9/9] drm/msm/a6xx: update a6xx_hw_init for A640 and A650
       [not found] <20200420140313.7263-1-jonathan@marek.ca>
                   ` (7 preceding siblings ...)
  2020-04-20 14:03 ` [PATCH 8/9] drm/msm/a6xx: enable GMU log Jonathan Marek
@ 2020-04-20 14:03 ` Jonathan Marek
  2020-04-21 16:48   ` Jordan Crouse
  8 siblings, 1 reply; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 14:03 UTC (permalink / raw)
  To: freedreno
  Cc: David Airlie, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sharat Masetty, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Akhil P Oommen, Sean Paul, open list

Adreno 640 and 650 GPUs need some registers set differently.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
---
 drivers/gpu/drm/msm/adreno/a6xx.xml.h | 14 +++++++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 56 ++++++++++++++++++++++-----
 2 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
index ed78fee2a262..47840b73cdda 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
@@ -1047,6 +1047,8 @@ enum a6xx_tex_type {
 
 #define REG_A6XX_CP_MISC_CNTL					0x00000840
 
+#define REG_A6XX_CP_APRIV_CNTL					0x00000844
+
 #define REG_A6XX_CP_ROQ_THRESHOLDS_1				0x000008c1
 
 #define REG_A6XX_CP_ROQ_THRESHOLDS_2				0x000008c2
@@ -1764,6 +1766,8 @@ static inline uint32_t A6XX_CP_PROTECT_REG_MASK_LEN(uint32_t val)
 
 #define REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL			0x00000010
 
+#define REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL			0x00000011
+
 #define REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL			0x0000001f
 
 #define REG_A6XX_RBBM_INT_CLEAR_CMD				0x00000037
@@ -2418,6 +2422,16 @@ static inline uint32_t A6XX_UCHE_CLIENT_PF_PERFSEL(uint32_t val)
 
 #define REG_A6XX_TPL1_NC_MODE_CNTL				0x0000b604
 
+#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0			0x0000b608
+
+#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1			0x0000b609
+
+#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2			0x0000b60a
+
+#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3			0x0000b60b
+
+#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4			0x0000b60c
+
 #define REG_A6XX_TPL1_PERFCTR_TP_SEL_0				0x0000b610
 
 #define REG_A6XX_TPL1_PERFCTR_TP_SEL_1				0x0000b611
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index a860d4970e10..e1eb34fa3a99 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -414,7 +414,17 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
 		a6xx_set_hwcg(gpu, true);
 
 	/* VBIF/GBIF start*/
-	gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3);
+	if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu)) {
+		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE0, 0x00071620);
+		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE1, 0x00071620);
+		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE2, 0x00071620);
+		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620);
+		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620);
+		gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x3);
+	} else {
+		gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3);
+	}
+
 	if (adreno_is_a630(adreno_gpu))
 		gpu_write(gpu, REG_A6XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009);
 
@@ -429,25 +439,35 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
 	gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_LO, 0xfffff000);
 	gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_HI, 0x0001ffff);
 
-	/* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */
-	gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO,
-		REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000);
+	if (!adreno_is_a650(adreno_gpu)) {
+		/* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */
+		gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO,
+			REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000);
 
-	gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO,
-		REG_A6XX_UCHE_GMEM_RANGE_MAX_HI,
-		0x00100000 + adreno_gpu->gmem - 1);
+		gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO,
+			REG_A6XX_UCHE_GMEM_RANGE_MAX_HI,
+			0x00100000 + adreno_gpu->gmem - 1);
+	}
 
 	gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804);
 	gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4);
 
-	gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0);
+	if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu))
+		gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140);
+	else
+		gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0);
 	gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c);
 
 	/* Setting the mem pool size */
 	gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128);
 
 	/* Setting the primFifo thresholds default values */
-	gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, (0x300 << 11));
+	if (adreno_is_a650(adreno_gpu))
+		gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300000);
+	else if (adreno_is_a640(adreno_gpu))
+		gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00200000);
+	else
+		gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, (0x300 << 11));
 
 	/* Set the AHB default slave response to "ERROR" */
 	gpu_write(gpu, REG_A6XX_CP_AHB_CNTL, 0x1);
@@ -471,6 +491,19 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
 
 	gpu_write(gpu, REG_A6XX_UCHE_CLIENT_PF, 1);
 
+	/* Set weights for bicubic filtering */
+	if (adreno_is_a650(adreno_gpu)) {
+		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0, 0);
+		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1,
+			0x3fe05ff4);
+		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2,
+			0x3fa0ebee);
+		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3,
+			0x3f5193ed);
+		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4,
+			0x3f0243f0);
+	}
+
 	/* Protect registers from the CP */
 	gpu_write(gpu, REG_A6XX_CP_PROTECT_CNTL, 0x00000003);
 
@@ -508,6 +541,11 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
 			A6XX_PROTECT_RDONLY(0x980, 0x4));
 	gpu_write(gpu, REG_A6XX_CP_PROTECT(25), A6XX_PROTECT_RW(0xa630, 0x0));
 
+	if (adreno_is_a650(adreno_gpu)) {
+		gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL,
+			(1 << 6) | (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1));
+	}
+
 	/* Enable interrupts */
 	gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_INT_MASK);
 
-- 
2.26.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 1/9] drm/msm/adreno: add A640/A650 to gpulist
  2020-04-20 14:03 ` [PATCH 1/9] drm/msm/adreno: add A640/A650 to gpulist Jonathan Marek
@ 2020-04-20 14:30   ` Greg Kroah-Hartman
  0 siblings, 0 replies; 18+ messages in thread
From: Greg Kroah-Hartman @ 2020-04-20 14:30 UTC (permalink / raw)
  To: Jonathan Marek
  Cc: Wambui Karuga, Douglas Anderson, open list, Jeffrey Hugo,
	David Airlie, freedreno, Sharat Masetty,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Bjorn Andersson,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Thomas Gleixner,
	AngeloGioacchino Del Regno, Sean Paul, Allison Randal,
	Brian Masney

On Mon, Apr 20, 2020 at 10:03:05AM -0400, Jonathan Marek wrote:
> Signed-off-by: Jonathan Marek <jonathan@marek.ca>
> ---
>  drivers/gpu/drm/msm/adreno/adreno_device.c | 24 ++++++++++++++++++++++
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c    |  2 +-
>  drivers/gpu/drm/msm/adreno/adreno_gpu.h    | 10 +++++++++
>  3 files changed, 35 insertions(+), 1 deletion(-)

I know I don't accept patches without any changelog text, maybe other
subsystem maintainers are more lax...
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 2/9] Revert "drm/msm/a6xx: Use the DMA API for GMU memory objects"
  2020-04-20 14:03 ` [PATCH 2/9] Revert "drm/msm/a6xx: Use the DMA API for GMU memory objects" Jonathan Marek
@ 2020-04-20 19:51   ` Bjorn Andersson
  2020-04-20 19:59     ` Jonathan Marek
  0 siblings, 1 reply; 18+ messages in thread
From: Bjorn Andersson @ 2020-04-20 19:51 UTC (permalink / raw)
  To: Jonathan Marek
  Cc: David Airlie, freedreno, Sharat Masetty,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Stephen Boyd,
	Michael J. Ruhl, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sean Paul, open list

On Mon 20 Apr 07:03 PDT 2020, Jonathan Marek wrote:

> This reverts commit a5fb8b918920c6f7706a8b5b8ea535a7f077a7f6.

Why?

> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 115 +++++++++++++++++++++++---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.h |   6 +-
>  2 files changed, 107 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index c4e71abbdd53..748cd379065f 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -2,7 +2,6 @@
>  /* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */
>  
>  #include <linux/clk.h>
> -#include <linux/dma-mapping.h>
>  #include <linux/interconnect.h>
>  #include <linux/pm_domain.h>
>  #include <linux/pm_opp.h>
> @@ -921,10 +920,21 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
>  
>  static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo)
>  {
> +	int count, i;
> +	u64 iova;
> +
>  	if (IS_ERR_OR_NULL(bo))
>  		return;
>  
> -	dma_free_wc(gmu->dev, bo->size, bo->virt, bo->iova);
> +	count = bo->size >> PAGE_SHIFT;
> +	iova = bo->iova;
> +
> +	for (i = 0; i < count; i++, iova += PAGE_SIZE) {
> +		iommu_unmap(gmu->domain, iova, PAGE_SIZE);
> +		__free_pages(bo->pages[i], 0);
> +	}
> +
> +	kfree(bo->pages);
>  	kfree(bo);
>  }
>  
> @@ -932,6 +942,7 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
>  		size_t size)
>  {
>  	struct a6xx_gmu_bo *bo;
> +	int ret, count, i;
>  
>  	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
>  	if (!bo)
> @@ -939,14 +950,86 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
>  
>  	bo->size = PAGE_ALIGN(size);
>  
> -	bo->virt = dma_alloc_wc(gmu->dev, bo->size, &bo->iova, GFP_KERNEL);
> +	count = bo->size >> PAGE_SHIFT;
>  
> -	if (!bo->virt) {
> +	bo->pages = kcalloc(count, sizeof(struct page *), GFP_KERNEL);
> +	if (!bo->pages) {
>  		kfree(bo);
>  		return ERR_PTR(-ENOMEM);
>  	}
>  
> +	for (i = 0; i < count; i++) {
> +		bo->pages[i] = alloc_page(GFP_KERNEL);
> +		if (!bo->pages[i])
> +			goto err;
> +	}
> +
> +	bo->iova = gmu->uncached_iova_base;
> +
> +	for (i = 0; i < count; i++) {
> +		ret = iommu_map(gmu->domain,
> +			bo->iova + (PAGE_SIZE * i),
> +			page_to_phys(bo->pages[i]), PAGE_SIZE,
> +			IOMMU_READ | IOMMU_WRITE);
> +
> +		if (ret) {
> +			DRM_DEV_ERROR(gmu->dev, "Unable to map GMU buffer object\n");
> +
> +			for (i = i - 1 ; i >= 0; i--)
> +				iommu_unmap(gmu->domain,
> +					bo->iova + (PAGE_SIZE * i),
> +					PAGE_SIZE);
> +
> +			goto err;
> +		}
> +	}
> +
> +	bo->virt = vmap(bo->pages, count, VM_IOREMAP,
> +		pgprot_writecombine(PAGE_KERNEL));
> +	if (!bo->virt)
> +		goto err;
> +
> +	/* Align future IOVA addresses on 1MB boundaries */
> +	gmu->uncached_iova_base += ALIGN(size, SZ_1M);
> +
>  	return bo;
> +
> +err:
> +	for (i = 0; i < count; i++) {
> +		if (bo->pages[i])
> +			__free_pages(bo->pages[i], 0);
> +	}
> +
> +	kfree(bo->pages);
> +	kfree(bo);
> +
> +	return ERR_PTR(-ENOMEM);
> +}
> +
> +static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu)
> +{
> +	int ret;
> +
> +	/*
> +	 * The GMU address space is hardcoded to treat the range
> +	 * 0x60000000 - 0x80000000 as un-cached memory. All buffers shared
> +	 * between the GMU and the CPU will live in this space
> +	 */
> +	gmu->uncached_iova_base = 0x60000000;
> +
> +
> +	gmu->domain = iommu_domain_alloc(&platform_bus_type);
> +	if (!gmu->domain)
> +		return -ENODEV;
> +
> +	ret = iommu_attach_device(gmu->domain, gmu->dev);
> +
> +	if (ret) {
> +		iommu_domain_free(gmu->domain);
> +		gmu->domain = NULL;
> +	}
> +
> +	return ret;
>  }
>  
>  /* Return the 'arc-level' for the given frequency */
> @@ -1206,6 +1289,10 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
>  
>  	a6xx_gmu_memory_free(gmu, gmu->hfi);
>  
> +	iommu_detach_device(gmu->domain, gmu->dev);
> +
> +	iommu_domain_free(gmu->domain);
> +
>  	free_irq(gmu->gmu_irq, gmu);
>  	free_irq(gmu->hfi_irq, gmu);
>  
> @@ -1226,15 +1313,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>  
>  	gmu->dev = &pdev->dev;
>  
> -	/* Pass force_dma false to require the DT to set the dma region */
> -	ret = of_dma_configure(gmu->dev, node, false);
> -	if (ret)
> -		return ret;
> -
> -	/* Set the mask after the of_dma_configure() */
> -	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(31));
> -	if (ret)
> -		return ret;
> +	of_dma_configure(gmu->dev, node, true);
>  
>  	/* Fow now, don't do anything fancy until we get our feet under us */
>  	gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
> @@ -1246,6 +1325,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>  	if (ret)
>  		goto err_put_device;
>  
> +	/* Set up the IOMMU context bank */
> +	ret = a6xx_gmu_memory_probe(gmu);
> +	if (ret)
> +		goto err_put_device;
> +
>  	/* Allocate memory for for the HFI queues */
>  	gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K);
>  	if (IS_ERR(gmu->hfi))
> @@ -1291,6 +1375,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>  err_memory:
>  	a6xx_gmu_memory_free(gmu, gmu->hfi);
>  
> +	if (gmu->domain) {
> +		iommu_detach_device(gmu->domain, gmu->dev);
> +
> +		iommu_domain_free(gmu->domain);
> +	}
>  	ret = -ENODEV;
>  
>  err_put_device:
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> index 4af65a36d5ca..2af91ed7ed0c 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> @@ -12,7 +12,8 @@
>  struct a6xx_gmu_bo {
>  	void *virt;
>  	size_t size;
> -	dma_addr_t iova;
> +	u64 iova;
> +	struct page **pages;
>  };
>  
>  /*
> @@ -48,6 +49,9 @@ struct a6xx_gmu {
>  	int hfi_irq;
>  	int gmu_irq;
>  
> +	struct iommu_domain *domain;
> +	u64 uncached_iova_base;
> +
>  	struct device *gxpd;
>  
>  	int idle_level;
> -- 
> 2.26.1
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 2/9] Revert "drm/msm/a6xx: Use the DMA API for GMU memory objects"
  2020-04-20 19:51   ` Bjorn Andersson
@ 2020-04-20 19:59     ` Jonathan Marek
  2020-04-20 21:16       ` Rob Clark
  0 siblings, 1 reply; 18+ messages in thread
From: Jonathan Marek @ 2020-04-20 19:59 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: David Airlie, freedreno, Sharat Masetty,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Stephen Boyd,
	Michael J. Ruhl, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sean Paul, open list

On 4/20/20 3:51 PM, Bjorn Andersson wrote:
> On Mon 20 Apr 07:03 PDT 2020, Jonathan Marek wrote:
> 
>> This reverts commit a5fb8b918920c6f7706a8b5b8ea535a7f077a7f6.
> 
> Why?
> 

It removes something I need for the next patches in the series, however 
I'm open to suggestions on a better solution (Jordan said he would check 
it out)

>> ---
>>   drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 115 +++++++++++++++++++++++---
>>   drivers/gpu/drm/msm/adreno/a6xx_gmu.h |   6 +-
>>   2 files changed, 107 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> index c4e71abbdd53..748cd379065f 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> @@ -2,7 +2,6 @@
>>   /* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */
>>   
>>   #include <linux/clk.h>
>> -#include <linux/dma-mapping.h>
>>   #include <linux/interconnect.h>
>>   #include <linux/pm_domain.h>
>>   #include <linux/pm_opp.h>
>> @@ -921,10 +920,21 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
>>   
>>   static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo)
>>   {
>> +	int count, i;
>> +	u64 iova;
>> +
>>   	if (IS_ERR_OR_NULL(bo))
>>   		return;
>>   
>> -	dma_free_wc(gmu->dev, bo->size, bo->virt, bo->iova);
>> +	count = bo->size >> PAGE_SHIFT;
>> +	iova = bo->iova;
>> +
>> +	for (i = 0; i < count; i++, iova += PAGE_SIZE) {
>> +		iommu_unmap(gmu->domain, iova, PAGE_SIZE);
>> +		__free_pages(bo->pages[i], 0);
>> +	}
>> +
>> +	kfree(bo->pages);
>>   	kfree(bo);
>>   }
>>   
>> @@ -932,6 +942,7 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
>>   		size_t size)
>>   {
>>   	struct a6xx_gmu_bo *bo;
>> +	int ret, count, i;
>>   
>>   	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
>>   	if (!bo)
>> @@ -939,14 +950,86 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
>>   
>>   	bo->size = PAGE_ALIGN(size);
>>   
>> -	bo->virt = dma_alloc_wc(gmu->dev, bo->size, &bo->iova, GFP_KERNEL);
>> +	count = bo->size >> PAGE_SHIFT;
>>   
>> -	if (!bo->virt) {
>> +	bo->pages = kcalloc(count, sizeof(struct page *), GFP_KERNEL);
>> +	if (!bo->pages) {
>>   		kfree(bo);
>>   		return ERR_PTR(-ENOMEM);
>>   	}
>>   
>> +	for (i = 0; i < count; i++) {
>> +		bo->pages[i] = alloc_page(GFP_KERNEL);
>> +		if (!bo->pages[i])
>> +			goto err;
>> +	}
>> +
>> +	bo->iova = gmu->uncached_iova_base;
>> +
>> +	for (i = 0; i < count; i++) {
>> +		ret = iommu_map(gmu->domain,
>> +			bo->iova + (PAGE_SIZE * i),
>> +			page_to_phys(bo->pages[i]), PAGE_SIZE,
>> +			IOMMU_READ | IOMMU_WRITE);
>> +
>> +		if (ret) {
>> +			DRM_DEV_ERROR(gmu->dev, "Unable to map GMU buffer object\n");
>> +
>> +			for (i = i - 1 ; i >= 0; i--)
>> +				iommu_unmap(gmu->domain,
>> +					bo->iova + (PAGE_SIZE * i),
>> +					PAGE_SIZE);
>> +
>> +			goto err;
>> +		}
>> +	}
>> +
>> +	bo->virt = vmap(bo->pages, count, VM_IOREMAP,
>> +		pgprot_writecombine(PAGE_KERNEL));
>> +	if (!bo->virt)
>> +		goto err;
>> +
>> +	/* Align future IOVA addresses on 1MB boundaries */
>> +	gmu->uncached_iova_base += ALIGN(size, SZ_1M);
>> +
>>   	return bo;
>> +
>> +err:
>> +	for (i = 0; i < count; i++) {
>> +		if (bo->pages[i])
>> +			__free_pages(bo->pages[i], 0);
>> +	}
>> +
>> +	kfree(bo->pages);
>> +	kfree(bo);
>> +
>> +	return ERR_PTR(-ENOMEM);
>> +}
>> +
>> +static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu)
>> +{
>> +	int ret;
>> +
>> +	/*
>> +	 * The GMU address space is hardcoded to treat the range
>> +	 * 0x60000000 - 0x80000000 as un-cached memory. All buffers shared
>> +	 * between the GMU and the CPU will live in this space
>> +	 */
>> +	gmu->uncached_iova_base = 0x60000000;
>> +
>> +
>> +	gmu->domain = iommu_domain_alloc(&platform_bus_type);
>> +	if (!gmu->domain)
>> +		return -ENODEV;
>> +
>> +	ret = iommu_attach_device(gmu->domain, gmu->dev);
>> +
>> +	if (ret) {
>> +		iommu_domain_free(gmu->domain);
>> +		gmu->domain = NULL;
>> +	}
>> +
>> +	return ret;
>>   }
>>   
>>   /* Return the 'arc-level' for the given frequency */
>> @@ -1206,6 +1289,10 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
>>   
>>   	a6xx_gmu_memory_free(gmu, gmu->hfi);
>>   
>> +	iommu_detach_device(gmu->domain, gmu->dev);
>> +
>> +	iommu_domain_free(gmu->domain);
>> +
>>   	free_irq(gmu->gmu_irq, gmu);
>>   	free_irq(gmu->hfi_irq, gmu);
>>   
>> @@ -1226,15 +1313,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>>   
>>   	gmu->dev = &pdev->dev;
>>   
>> -	/* Pass force_dma false to require the DT to set the dma region */
>> -	ret = of_dma_configure(gmu->dev, node, false);
>> -	if (ret)
>> -		return ret;
>> -
>> -	/* Set the mask after the of_dma_configure() */
>> -	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(31));
>> -	if (ret)
>> -		return ret;
>> +	of_dma_configure(gmu->dev, node, true);
>>   
>>   	/* Fow now, don't do anything fancy until we get our feet under us */
>>   	gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
>> @@ -1246,6 +1325,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>>   	if (ret)
>>   		goto err_put_device;
>>   
>> +	/* Set up the IOMMU context bank */
>> +	ret = a6xx_gmu_memory_probe(gmu);
>> +	if (ret)
>> +		goto err_put_device;
>> +
>>   	/* Allocate memory for for the HFI queues */
>>   	gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K);
>>   	if (IS_ERR(gmu->hfi))
>> @@ -1291,6 +1375,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>>   err_memory:
>>   	a6xx_gmu_memory_free(gmu, gmu->hfi);
>>   
>> +	if (gmu->domain) {
>> +		iommu_detach_device(gmu->domain, gmu->dev);
>> +
>> +		iommu_domain_free(gmu->domain);
>> +	}
>>   	ret = -ENODEV;
>>   
>>   err_put_device:
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
>> index 4af65a36d5ca..2af91ed7ed0c 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
>> @@ -12,7 +12,8 @@
>>   struct a6xx_gmu_bo {
>>   	void *virt;
>>   	size_t size;
>> -	dma_addr_t iova;
>> +	u64 iova;
>> +	struct page **pages;
>>   };
>>   
>>   /*
>> @@ -48,6 +49,9 @@ struct a6xx_gmu {
>>   	int hfi_irq;
>>   	int gmu_irq;
>>   
>> +	struct iommu_domain *domain;
>> +	u64 uncached_iova_base;
>> +
>>   	struct device *gxpd;
>>   
>>   	int idle_level;
>> -- 
>> 2.26.1
>>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 2/9] Revert "drm/msm/a6xx: Use the DMA API for GMU memory objects"
  2020-04-20 19:59     ` Jonathan Marek
@ 2020-04-20 21:16       ` Rob Clark
  0 siblings, 0 replies; 18+ messages in thread
From: Rob Clark @ 2020-04-20 21:16 UTC (permalink / raw)
  To: Jonathan Marek
  Cc: David Airlie, freedreno, Sharat Masetty, open list,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Bjorn Andersson,
	Michael J. Ruhl, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Stephen Boyd, Sean Paul

On Mon, Apr 20, 2020 at 12:59 PM Jonathan Marek <jonathan@marek.ca> wrote:
>
> On 4/20/20 3:51 PM, Bjorn Andersson wrote:
> > On Mon 20 Apr 07:03 PDT 2020, Jonathan Marek wrote:
> >
> >> This reverts commit a5fb8b918920c6f7706a8b5b8ea535a7f077a7f6.
> >
> > Why?
> >
>
> It removes something I need for the next patches in the series, however
> I'm open to suggestions on a better solution (Jordan said he would check
> it out)

when you repost (if we end up keeping this approach), please add a
description of the reason in the commit msg of the revert.. it makes
it easier to review and less confusing in git history

BR,
-R


> >> ---
> >>   drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 115 +++++++++++++++++++++++---
> >>   drivers/gpu/drm/msm/adreno/a6xx_gmu.h |   6 +-
> >>   2 files changed, 107 insertions(+), 14 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> >> index c4e71abbdd53..748cd379065f 100644
> >> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> >> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> >> @@ -2,7 +2,6 @@
> >>   /* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */
> >>
> >>   #include <linux/clk.h>
> >> -#include <linux/dma-mapping.h>
> >>   #include <linux/interconnect.h>
> >>   #include <linux/pm_domain.h>
> >>   #include <linux/pm_opp.h>
> >> @@ -921,10 +920,21 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu)
> >>
> >>   static void a6xx_gmu_memory_free(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo)
> >>   {
> >> +    int count, i;
> >> +    u64 iova;
> >> +
> >>      if (IS_ERR_OR_NULL(bo))
> >>              return;
> >>
> >> -    dma_free_wc(gmu->dev, bo->size, bo->virt, bo->iova);
> >> +    count = bo->size >> PAGE_SHIFT;
> >> +    iova = bo->iova;
> >> +
> >> +    for (i = 0; i < count; i++, iova += PAGE_SIZE) {
> >> +            iommu_unmap(gmu->domain, iova, PAGE_SIZE);
> >> +            __free_pages(bo->pages[i], 0);
> >> +    }
> >> +
> >> +    kfree(bo->pages);
> >>      kfree(bo);
> >>   }
> >>
> >> @@ -932,6 +942,7 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
> >>              size_t size)
> >>   {
> >>      struct a6xx_gmu_bo *bo;
> >> +    int ret, count, i;
> >>
> >>      bo = kzalloc(sizeof(*bo), GFP_KERNEL);
> >>      if (!bo)
> >> @@ -939,14 +950,86 @@ static struct a6xx_gmu_bo *a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu,
> >>
> >>      bo->size = PAGE_ALIGN(size);
> >>
> >> -    bo->virt = dma_alloc_wc(gmu->dev, bo->size, &bo->iova, GFP_KERNEL);
> >> +    count = bo->size >> PAGE_SHIFT;
> >>
> >> -    if (!bo->virt) {
> >> +    bo->pages = kcalloc(count, sizeof(struct page *), GFP_KERNEL);
> >> +    if (!bo->pages) {
> >>              kfree(bo);
> >>              return ERR_PTR(-ENOMEM);
> >>      }
> >>
> >> +    for (i = 0; i < count; i++) {
> >> +            bo->pages[i] = alloc_page(GFP_KERNEL);
> >> +            if (!bo->pages[i])
> >> +                    goto err;
> >> +    }
> >> +
> >> +    bo->iova = gmu->uncached_iova_base;
> >> +
> >> +    for (i = 0; i < count; i++) {
> >> +            ret = iommu_map(gmu->domain,
> >> +                    bo->iova + (PAGE_SIZE * i),
> >> +                    page_to_phys(bo->pages[i]), PAGE_SIZE,
> >> +                    IOMMU_READ | IOMMU_WRITE);
> >> +
> >> +            if (ret) {
> >> +                    DRM_DEV_ERROR(gmu->dev, "Unable to map GMU buffer object\n");
> >> +
> >> +                    for (i = i - 1 ; i >= 0; i--)
> >> +                            iommu_unmap(gmu->domain,
> >> +                                    bo->iova + (PAGE_SIZE * i),
> >> +                                    PAGE_SIZE);
> >> +
> >> +                    goto err;
> >> +            }
> >> +    }
> >> +
> >> +    bo->virt = vmap(bo->pages, count, VM_IOREMAP,
> >> +            pgprot_writecombine(PAGE_KERNEL));
> >> +    if (!bo->virt)
> >> +            goto err;
> >> +
> >> +    /* Align future IOVA addresses on 1MB boundaries */
> >> +    gmu->uncached_iova_base += ALIGN(size, SZ_1M);
> >> +
> >>      return bo;
> >> +
> >> +err:
> >> +    for (i = 0; i < count; i++) {
> >> +            if (bo->pages[i])
> >> +                    __free_pages(bo->pages[i], 0);
> >> +    }
> >> +
> >> +    kfree(bo->pages);
> >> +    kfree(bo);
> >> +
> >> +    return ERR_PTR(-ENOMEM);
> >> +}
> >> +
> >> +static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu)
> >> +{
> >> +    int ret;
> >> +
> >> +    /*
> >> +     * The GMU address space is hardcoded to treat the range
> >> +     * 0x60000000 - 0x80000000 as un-cached memory. All buffers shared
> >> +     * between the GMU and the CPU will live in this space
> >> +     */
> >> +    gmu->uncached_iova_base = 0x60000000;
> >> +
> >> +
> >> +    gmu->domain = iommu_domain_alloc(&platform_bus_type);
> >> +    if (!gmu->domain)
> >> +            return -ENODEV;
> >> +
> >> +    ret = iommu_attach_device(gmu->domain, gmu->dev);
> >> +
> >> +    if (ret) {
> >> +            iommu_domain_free(gmu->domain);
> >> +            gmu->domain = NULL;
> >> +    }
> >> +
> >> +    return ret;
> >>   }
> >>
> >>   /* Return the 'arc-level' for the given frequency */
> >> @@ -1206,6 +1289,10 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
> >>
> >>      a6xx_gmu_memory_free(gmu, gmu->hfi);
> >>
> >> +    iommu_detach_device(gmu->domain, gmu->dev);
> >> +
> >> +    iommu_domain_free(gmu->domain);
> >> +
> >>      free_irq(gmu->gmu_irq, gmu);
> >>      free_irq(gmu->hfi_irq, gmu);
> >>
> >> @@ -1226,15 +1313,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
> >>
> >>      gmu->dev = &pdev->dev;
> >>
> >> -    /* Pass force_dma false to require the DT to set the dma region */
> >> -    ret = of_dma_configure(gmu->dev, node, false);
> >> -    if (ret)
> >> -            return ret;
> >> -
> >> -    /* Set the mask after the of_dma_configure() */
> >> -    ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(31));
> >> -    if (ret)
> >> -            return ret;
> >> +    of_dma_configure(gmu->dev, node, true);
> >>
> >>      /* Fow now, don't do anything fancy until we get our feet under us */
> >>      gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
> >> @@ -1246,6 +1325,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
> >>      if (ret)
> >>              goto err_put_device;
> >>
> >> +    /* Set up the IOMMU context bank */
> >> +    ret = a6xx_gmu_memory_probe(gmu);
> >> +    if (ret)
> >> +            goto err_put_device;
> >> +
> >>      /* Allocate memory for for the HFI queues */
> >>      gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K);
> >>      if (IS_ERR(gmu->hfi))
> >> @@ -1291,6 +1375,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
> >>   err_memory:
> >>      a6xx_gmu_memory_free(gmu, gmu->hfi);
> >>
> >> +    if (gmu->domain) {
> >> +            iommu_detach_device(gmu->domain, gmu->dev);
> >> +
> >> +            iommu_domain_free(gmu->domain);
> >> +    }
> >>      ret = -ENODEV;
> >>
> >>   err_put_device:
> >> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> >> index 4af65a36d5ca..2af91ed7ed0c 100644
> >> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> >> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> >> @@ -12,7 +12,8 @@
> >>   struct a6xx_gmu_bo {
> >>      void *virt;
> >>      size_t size;
> >> -    dma_addr_t iova;
> >> +    u64 iova;
> >> +    struct page **pages;
> >>   };
> >>
> >>   /*
> >> @@ -48,6 +49,9 @@ struct a6xx_gmu {
> >>      int hfi_irq;
> >>      int gmu_irq;
> >>
> >> +    struct iommu_domain *domain;
> >> +    u64 uncached_iova_base;
> >> +
> >>      struct device *gxpd;
> >>
> >>      int idle_level;
> >> --
> >> 2.26.1
> >>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 4/9] drm/msm/a6xx: HFI v2 for A640 and A650
  2020-04-20 14:03 ` [PATCH 4/9] drm/msm/a6xx: HFI v2 for A640 and A650 Jonathan Marek
@ 2020-04-21 16:30   ` Jordan Crouse
  2020-04-21 16:52     ` Jonathan Marek
  0 siblings, 1 reply; 18+ messages in thread
From: Jordan Crouse @ 2020-04-21 16:30 UTC (permalink / raw)
  To: Jonathan Marek
  Cc: David Airlie, freedreno, Sharat Masetty, Akhil P Oommen,
	open list:DRM DRIVER FOR MSM ADRENO GPU, open list,
	Michael J. Ruhl, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sean Paul

On Mon, Apr 20, 2020 at 10:03:08AM -0400, Jonathan Marek wrote:
> Signed-off-by: Jonathan Marek <jonathan@marek.ca>
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c |  68 ++++++++++++---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.h |   7 ++
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c |   6 +-
>  drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 117 ++++++++++++++++++++++++--
>  drivers/gpu/drm/msm/adreno/a6xx_hfi.h |  50 ++++++++++-
>  5 files changed, 224 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index c6ecb3189ec5..dc2d69837110 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -126,8 +126,6 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
>  	if (ret)
>  		dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
>  
> -	gmu->freq = gmu->gpu_freqs[index];
> -
>  	/*
>  	 * Eventually we will want to scale the path vote with the frequency but
>  	 * for now leave it at max so that the performance is nominal.
> @@ -151,7 +149,12 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
>  
>  	gmu->current_perf_index = perf_index;
>  
> -	__a6xx_gmu_set_freq(gmu, perf_index);
> +	if (gmu->legacy)
> +		__a6xx_gmu_set_freq(gmu, perf_index);
> +	else
> +		a6xx_hfi_set_freq(gmu, perf_index);

Welcome to the first great GMU schism. There are going to be a lot of these if()
statements and my guess is that it won't get any cleaner in the future.

The best option in my opinion would be to make two separate GMU implementations
and select the probe either from the gpu list or the compatible string and use
function pointers for the functions that are called from a6xx_gpu.c and
a6xx_gpu_state.c.

We _could_ make the gmu->legacy thing work but if someday there is a another
schism we would be sad that we didn't do the ground work now.

We could also do the same for HFI, but I think there is a bit less of a delta
there and there isn't a harm in having a _v1 function or two laying around.

> +
> +	gmu->freq = gmu->gpu_freqs[perf_index];
>  }
>  
>  unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu)
> @@ -231,19 +234,26 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
>  
>  	switch (state) {
>  	case GMU_OOB_GPU_SET:
> -		request = GMU_OOB_GPU_SET_REQUEST;
> -		ack = GMU_OOB_GPU_SET_ACK;
> +		if (gmu->legacy) {
> +			request = GMU_OOB_GPU_SET_REQUEST;
> +			ack = GMU_OOB_GPU_SET_ACK;
> +		} else {
> +			request = GMU_OOB_GPU_SET_REQUEST_NEW;
> +			ack = GMU_OOB_GPU_SET_ACK_NEW;
> +		}
>  		name = "GPU_SET";
>  		break;
>  	case GMU_OOB_BOOT_SLUMBER:
>  		request = GMU_OOB_BOOT_SLUMBER_REQUEST;
>  		ack = GMU_OOB_BOOT_SLUMBER_ACK;
>  		name = "BOOT_SLUMBER";
> +		WARN_ON(!gmu->legacy);

This is unlikely to be the case - these should only be called from within the
GMU code and we should be able to control it.

>  		break;
>  	case GMU_OOB_DCVS_SET:
>  		request = GMU_OOB_DCVS_REQUEST;
>  		ack = GMU_OOB_DCVS_ACK;
>  		name = "GPU_DCVS";
> +		WARN_ON(!gmu->legacy);

Same.

>  		break;
>  	default:
>  		return -EINVAL;
> @@ -271,6 +281,13 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
>  /* Clear a pending OOB state in the GMU */
>  void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
>  {
> +	if (!gmu->legacy) {
> +		WARN_ON(state != GMU_OOB_GPU_SET);
> +		gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
> +			1 << GMU_OOB_GPU_SET_CLEAR_NEW);
> +		return;
> +	}

A good example of the usefulness of per-implementation functions.

> +
>  	switch (state) {
>  	case GMU_OOB_GPU_SET:
>  		gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
> @@ -293,6 +310,9 @@ static int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
>  	int ret;
>  	u32 val;
>  
> +	if (!gmu->legacy)
> +		return 0;
> +
>  	gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000);
>  
>  	ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, val,
> @@ -312,6 +332,9 @@ static void a6xx_sptprac_disable(struct a6xx_gmu *gmu)
>  	u32 val;
>  	int ret;
>  
> +	if (!gmu->legacy)
> +		return;
> +
>  	/* Make sure retention is on */
>  	gmu_rmw(gmu, REG_A6XX_GPU_CC_GX_GDSCR, 0, (1 << 11));
>  
> @@ -355,6 +378,11 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
>  	if (gmu->idle_level < GMU_IDLE_STATE_SPTP)
>  		a6xx_sptprac_disable(gmu);
>  
> +	if (!gmu->legacy) {
> +		ret = a6xx_hfi_send_prep_slumber(gmu);
> +		goto out;
> +	}
> +
>  	/* Tell the GMU to get ready to slumber */
>  	gmu_write(gmu, REG_A6XX_GMU_BOOT_SLUMBER_OPTION, 1);
>  
> @@ -370,6 +398,7 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
>  		}
>  	}
>  
> +out:
>  	/* Put fence into allow mode */
>  	gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0);
>  	return ret;
> @@ -639,9 +668,11 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
>  	if (ret)
>  		return ret;
>  
> -	ret = a6xx_gmu_gfx_rail_on(gmu);
> -	if (ret)
> -		return ret;
> +	if (gmu->legacy) {
> +		ret = a6xx_gmu_gfx_rail_on(gmu);
> +		if (ret)
> +			return ret;
> +	}
>  
>  	/* Enable SPTP_PC if the CPU is responsible for it */
>  	if (gmu->idle_level < GMU_IDLE_STATE_SPTP) {
> @@ -760,7 +791,10 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
>  	enable_irq(gmu->hfi_irq);
>  
>  	/* Set the GPU to the current freq */
> -	__a6xx_gmu_set_freq(gmu, gmu->current_perf_index);
> +	if (gmu->legacy)
> +		__a6xx_gmu_set_freq(gmu, gmu->current_perf_index);
> +	else
> +		a6xx_hfi_set_freq(gmu, gmu->current_perf_index);
>  
>  	/*
>  	 * "enable" the GX power domain which won't actually do anything but it
> @@ -1305,6 +1339,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
>  
>  int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>  {
> +	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
>  	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
>  	struct platform_device *pdev = of_find_device_by_node(node);
>  	int ret;
> @@ -1331,16 +1366,21 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>  	if (ret)
>  		goto err_put_device;
>  
> +	if (!adreno_is_a640(adreno_gpu) && !adreno_is_a650(adreno_gpu)) {
> +		/* HFI v1, no sptprac */

This comment isn't accurate, 630 and 618 have sptprac, 640 and 650 do not need
it.

> +		gmu->legacy = true;
> +
> +		/* Allocate memory for the GMU debug region */
> +		gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
> +		if (IS_ERR(gmu->debug))
> +			goto err_memory;
> +	}
> +
>  	/* Allocate memory for for the HFI queues */
>  	gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
>  	if (IS_ERR(gmu->hfi))
>  		goto err_memory;
>  
> -	/* Allocate memory for the GMU debug region */
> -	gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
> -	if (IS_ERR(gmu->debug))
> -		goto err_memory;
> -
>  	/* Map the GMU registers */
>  	gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
>  	if (IS_ERR(gmu->mmio))
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> index 2af91ed7ed0c..781714ffaa91 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> @@ -80,6 +80,7 @@ struct a6xx_gmu {
>  
>  	bool initialized;
>  	bool hung;
> +	bool legacy; /* a618 or a630 */
>  };
>  
>  static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
> @@ -160,10 +161,16 @@ enum a6xx_gmu_oob_state {
>  #define GMU_OOB_GPU_SET_ACK	24
>  #define GMU_OOB_GPU_SET_CLEAR	24
>  
> +#define GMU_OOB_GPU_SET_REQUEST_NEW	30
> +#define GMU_OOB_GPU_SET_ACK_NEW		31
> +#define GMU_OOB_GPU_SET_CLEAR_NEW	31
> +
>  
>  void a6xx_hfi_init(struct a6xx_gmu *gmu);
>  int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
>  void a6xx_hfi_stop(struct a6xx_gmu *gmu);
> +int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu);
> +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index);
>  
>  bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
>  bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index 68af24150de5..a860d4970e10 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -566,8 +566,10 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
>  	 */
>  	a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
>  
> -	/* Take the GMU out of its special boot mode */
> -	a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
> +	if (a6xx_gpu->gmu.legacy) {
> +		/* Take the GMU out of its special boot mode */
> +		a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
> +	}
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
> index e450e0b97211..3d4b142d8fb3 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
> @@ -17,10 +17,14 @@ static const char * const a6xx_hfi_msg_id[] = {
>  	HFI_MSG_ID(HFI_H2F_MSG_BW_TABLE),
>  	HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),
>  	HFI_MSG_ID(HFI_H2F_MSG_TEST),
> +	HFI_MSG_ID(HFI_H2F_MSG_START),
> +	HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START),
> +	HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE),
> +	HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER),
>  };
>  
> -static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data,
> -		u32 dwords)
> +static int a6xx_hfi_queue_read(struct a6xx_gmu *gmu,
> +	struct a6xx_hfi_queue *queue, u32 *data, u32 dwords)
>  {
>  	struct a6xx_hfi_queue_header *header = queue->header;
>  	u32 i, hdr, index = header->read_index;
> @@ -48,6 +52,9 @@ static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data,
>  		index = (index + 1) % header->size;
>  	}
>  
> +	if (!gmu->legacy)
> +		index = ALIGN(index, 4) % header->size;
> +
>  	header->read_index = index;
>  	return HFI_HEADER_SIZE(hdr);
>  }
> @@ -73,6 +80,12 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu,
>  		index = (index + 1) % header->size;
>  	}
>  
> +	/* Cookify any non used data at the end of the write buffer */
> +	if (!gmu->legacy) {
> +		for (; index % 4; index = (index + 1) % header->size)
> +			queue->data[index] = 0xfafafafa;
> +	}
> +
>  	header->write_index = index;
>  	spin_unlock(&queue->lock);
>  
> @@ -106,7 +119,7 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum,
>  		struct a6xx_hfi_msg_response resp;
>  
>  		/* Get the next packet */
> -		ret = a6xx_hfi_queue_read(queue, (u32 *) &resp,
> +		ret = a6xx_hfi_queue_read(gmu, queue, (u32 *) &resp,
>  			sizeof(resp) >> 2);
>  
>  		/* If the queue is empty our response never made it */
> @@ -195,6 +208,28 @@ static int a6xx_hfi_get_fw_version(struct a6xx_gmu *gmu, u32 *version)
>  		version, sizeof(*version));
>  }
>  
> +static int a6xx_hfi_send_perf_table_v1(struct a6xx_gmu *gmu)
> +{
> +	struct a6xx_hfi_msg_perf_table_v1 msg = { 0 };
> +	int i;
> +
> +	msg.num_gpu_levels = gmu->nr_gpu_freqs;
> +	msg.num_gmu_levels = gmu->nr_gmu_freqs;
> +
> +	for (i = 0; i < gmu->nr_gpu_freqs; i++) {
> +		msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
> +		msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
> +	}
> +
> +	for (i = 0; i < gmu->nr_gmu_freqs; i++) {
> +		msg.cx_votes[i].vote = gmu->cx_arc_votes[i];
> +		msg.cx_votes[i].freq = gmu->gmu_freqs[i] / 1000;
> +	}
> +
> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PERF_TABLE, &msg, sizeof(msg),
> +		NULL, 0);
> +}
> +
>  static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
>  {
>  	struct a6xx_hfi_msg_perf_table msg = { 0 };
> @@ -205,6 +240,7 @@ static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
>  
>  	for (i = 0; i < gmu->nr_gpu_freqs; i++) {
>  		msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
> +		msg.gx_votes[i].acd = 0xffffffff;
>  		msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
>  	}
>  
> @@ -306,7 +342,45 @@ static int a6xx_hfi_send_test(struct a6xx_gmu *gmu)
>  		NULL, 0);
>  }
>  
> -int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
> +int a6xx_hfi_send_start(struct a6xx_gmu *gmu)
> +{
> +	struct a6xx_hfi_msg_start msg = { 0 };
> +
> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_START, &msg, sizeof(msg),
> +		NULL, 0);
> +}
> +
> +int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu)
> +{
> +	struct a6xx_hfi_msg_core_fw_start msg = { 0 };
> +
> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_CORE_FW_START, &msg,
> +		sizeof(msg), NULL, 0);
> +}
> +
> +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index)
> +{
> +	struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 };
> +
> +	msg.ack_type = 1; /* blocking */
> +	msg.freq = index;
> +	msg.bw = 0; /* TODO: bus scaling */
> +
> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg,
> +		sizeof(msg), NULL, 0);
> +}
> +
> +int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu)
> +{
> +	struct a6xx_hfi_prep_slumber_cmd msg = { 0 };
> +
> +	/* TODO: should freq and bw fields be non-zero ? */
> +
> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PREPARE_SLUMBER, &msg,
> +		sizeof(msg), NULL, 0);
> +}
> +
> +static int a6xx_hfi_start_v1(struct a6xx_gmu *gmu, int boot_state)
>  {
>  	int ret;
>  
> @@ -324,7 +398,7 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
>  	 * the GMU firmware
>  	 */
>  
> -	ret = a6xx_hfi_send_perf_table(gmu);
> +	ret = a6xx_hfi_send_perf_table_v1(gmu);
>  	if (ret)
>  		return ret;
>  
> @@ -341,6 +415,37 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
>  	return 0;
>  }
>  
> +int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
> +{
> +	int ret;
> +
> +	if (gmu->legacy)
> +		return a6xx_hfi_start_v1(gmu, boot_state);
> +
> +
> +	ret = a6xx_hfi_send_perf_table(gmu);
> +	if (ret)
> +		return ret;
> +
> +	ret = a6xx_hfi_send_bw_table(gmu);
> +	if (ret)
> +		return ret;
> +
> +	ret = a6xx_hfi_send_core_fw_start(gmu);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * Downstream driver sends this in its "a6xx_hw_init" equivalent,
> +	 * but seems to be no harm in sending it here
> +	 */
> +	ret = a6xx_hfi_send_start(gmu);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
>  void a6xx_hfi_stop(struct a6xx_gmu *gmu)
>  {
>  	int i;
> @@ -415,5 +520,5 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu)
>  	/* GMU response queue */
>  	offset += SZ_4K;
>  	a6xx_hfi_queue_init(&gmu->queues[1], &headers[1], hfi->virt + offset,
> -		hfi->iova + offset, 4);
> +		hfi->iova + offset, gmu->legacy ? 4 : 1);
>  }
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
> index 60d1319fa44f..2bd670ca42d6 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
> @@ -51,7 +51,8 @@ struct a6xx_hfi_queue {
>  /* HFI message types */
>  
>  #define HFI_MSG_CMD 0
> -#define HFI_MSG_ACK 2
> +#define HFI_MSG_ACK 1
> +#define HFI_MSG_ACK_V1 2
>  
>  #define HFI_F2H_MSG_ACK 126
>  
> @@ -94,7 +95,13 @@ struct perf_level {
>  	u32 freq;
>  };
>  
> -struct a6xx_hfi_msg_perf_table {
> +struct perf_gx_level {
> +	u32 vote;
> +	u32 acd;
> +	u32 freq;
> +};

These all need to be __packed for the usual sad reasons.

> +
> +struct a6xx_hfi_msg_perf_table_v1 {
>  	u32 header;
>  	u32 num_gpu_levels;
>  	u32 num_gmu_levels;
> @@ -103,6 +110,15 @@ struct a6xx_hfi_msg_perf_table {
>  	struct perf_level cx_votes[4];
>  };
>  
> +struct a6xx_hfi_msg_perf_table {
> +	u32 header;
> +	u32 num_gpu_levels;
> +	u32 num_gmu_levels;
> +
> +	struct perf_gx_level gx_votes[16];
> +	struct perf_level cx_votes[4];
> +};
> +
>  #define HFI_H2F_MSG_BW_TABLE 3
>  
>  struct a6xx_hfi_msg_bw_table {
> @@ -124,4 +140,34 @@ struct a6xx_hfi_msg_test {
>  	u32 header;
>  };
>  
> +#define HFI_H2F_MSG_START 10
> +
> +struct a6xx_hfi_msg_start {
> +	u32 header;
> +};
> +
> +#define HFI_H2F_MSG_CORE_FW_START 14
> +
> +struct a6xx_hfi_msg_core_fw_start {
> +	u32 header;
> +	u32 handle;
> +};
> +
> +#define HFI_H2F_MSG_GX_BW_PERF_VOTE 30
> +
> +struct a6xx_hfi_gx_bw_perf_vote_cmd {
> +	u32 header;
> +	u32 ack_type;
> +	u32 freq;
> +	u32 bw;
> +};
> +
> +#define HFI_H2F_MSG_PREPARE_SLUMBER 33
> +
> +struct a6xx_hfi_prep_slumber_cmd {
> +	u32 header;
> +	u32 bw;
> +	u32 freq;
> +};
> +
>  #endif
> -- 
> 2.26.1
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 7/9] drm/msm/a6xx: gmu_pdc register values for A640 and A650
  2020-04-20 14:03 ` [PATCH 7/9] drm/msm/a6xx: gmu_pdc register values for A640 and A650 Jonathan Marek
@ 2020-04-21 16:34   ` Jordan Crouse
  0 siblings, 0 replies; 18+ messages in thread
From: Jordan Crouse @ 2020-04-21 16:34 UTC (permalink / raw)
  To: Jonathan Marek
  Cc: David Airlie, freedreno, Sharat Masetty, open list,
	open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Sean Paul

On Mon, Apr 20, 2020 at 10:03:11AM -0400, Jonathan Marek wrote:
> Signed-off-by: Jonathan Marek <jonathan@marek.ca>

I was wondering where this was.  I don't think there is any reason to not squash
this into the previous patch since the GMU won't be operational without it.

> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index 3e51939eb867..b583bf6e293b 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -469,10 +469,18 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
>  	struct platform_device *pdev = to_platform_device(gmu->dev);
>  	void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc");
>  	void __iomem *seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq");
> +	uint32_t pdc_address_offset;
>  
>  	if (!pdcptr || !seqptr)
>  		goto err;
>  
> +	if (adreno_is_a618(adreno_gpu) || adreno_is_a640(adreno_gpu))
> +		pdc_address_offset = 0x30090;
> +	else if (adreno_is_a650(adreno_gpu))
> +		pdc_address_offset = 0x300a0;
> +	else
> +		pdc_address_offset = 0x30080;
> +

>  	/* Disable SDE clock gating */
>  	gmu_write_rscc(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));
>  
> @@ -523,10 +531,7 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
>  	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 4, 0x0);
>  
>  	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID + 8, 0x10108);
> -	if (adreno_is_a618(adreno_gpu))
> -		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30090);
> -	else
> -		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30080);
> +	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, pdc_address_offset);
>  	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 8, 0x0);
>  
>  	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD_ENABLE_BANK, 7);
> @@ -538,17 +543,12 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
>  
>  	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 4, 0x10108);
>  	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 4, 0x30000);
> -	if (adreno_is_a618(adreno_gpu))
> +	if (adreno_is_a618(adreno_gpu) || adreno_is_a650(adreno_gpu))
>  		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x2);
>  	else
>  		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x3);
> -
> -
>  	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 8, 0x10108);
> -	if (adreno_is_a618(adreno_gpu))
> -		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30090);
> -	else
> -		pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30080);
> +	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, pdc_address_offset);
>  	pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 8, 0x3);
>  
>  	/* Setup GPU PDC */
> -- 
> 2.26.1
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [Freedreno] [PATCH 8/9] drm/msm/a6xx: enable GMU log
  2020-04-20 14:03 ` [PATCH 8/9] drm/msm/a6xx: enable GMU log Jonathan Marek
@ 2020-04-21 16:38   ` Jordan Crouse
  0 siblings, 0 replies; 18+ messages in thread
From: Jordan Crouse @ 2020-04-21 16:38 UTC (permalink / raw)
  To: Jonathan Marek
  Cc: Sean Paul, David Airlie, open list:DRM DRIVER FOR MSM ADRENO GPU,
	Sharat Masetty, open list,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Stephen Boyd,
	Michael J. Ruhl, freedreno

On Mon, Apr 20, 2020 at 10:03:12AM -0400, Jonathan Marek wrote:
> This is required for a650 to work.
> 
> Signed-off-by: Jonathan Marek <jonathan@marek.ca>
> ---
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c     | 16 ++++++++++++++++
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.h     |  1 +
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h |  4 ++++
>  3 files changed, 21 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> index b583bf6e293b..1cdb7c832b87 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
> @@ -198,6 +198,12 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu)
>  	u32 val;
>  
>  	gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);
> +
> +	/* Set the log wptr index
> +	 * note: downstream saves the value in poweroff and restores it here
> +	 */
> +	gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP, 0);
> +
>  	gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0);
>  
>  	ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, val,
> @@ -739,6 +745,9 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
>  
>  	gmu_write(gmu, REG_A6XX_GMU_HFI_SFR_ADDR, chipid);
>  
> +	gmu_write(gmu, REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG,
> +		  gmu->log->iova | (gmu->log->size / SZ_4K - 1));
> +
>  	/* Set up the lowest idle level on the GMU */
>  	a6xx_gmu_power_config(gmu);
>  
> @@ -1416,6 +1425,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
>  	a6xx_gmu_memory_free(gmu, gmu->dcache);
>  	a6xx_gmu_memory_free(gmu, gmu->dummy);
>  	a6xx_gmu_memory_free(gmu, gmu->debug);
> +	a6xx_gmu_memory_free(gmu, gmu->log);
>  	a6xx_gmu_memory_free(gmu, gmu->hfi);
>  
>  	iommu_detach_device(gmu->domain, gmu->dev);
> @@ -1495,6 +1505,11 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>  	if (IS_ERR(gmu->hfi))
>  		goto err_memory;
>  
> +	/* Allocate memory for the GMU log region */
> +	gmu->log = a6xx_gmu_memory_alloc(gmu, SZ_4K, 0);
> +	if (IS_ERR(gmu->log))
> +		goto err_memory;
> +
>  	/* Map the GMU registers */
>  	gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
>  	if (IS_ERR(gmu->mmio))
> @@ -1542,6 +1557,7 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>  	a6xx_gmu_memory_free(gmu, gmu->dcache);
>  	a6xx_gmu_memory_free(gmu, gmu->dummy);
>  	a6xx_gmu_memory_free(gmu, gmu->debug);
> +	a6xx_gmu_memory_free(gmu, gmu->log);
>  	a6xx_gmu_memory_free(gmu, gmu->hfi);

This is starting to feel like we could use some devres style garbage collection.

>  
>  	if (gmu->domain) {
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> index abd425ca6682..589b9b0c348e 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
> @@ -59,6 +59,7 @@ struct a6xx_gmu {
>  
>  	struct a6xx_gmu_bo *hfi;
>  	struct a6xx_gmu_bo *debug;
> +	struct a6xx_gmu_bo *log;
>  	struct a6xx_gmu_bo *icache;
>  	struct a6xx_gmu_bo *dcache;
>  	struct a6xx_gmu_bo *dummy;
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
> index b4357ea550ec..176ae94d9fe6 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
> @@ -205,6 +205,10 @@ static inline uint32_t A6XX_GMU_GPU_NAP_CTRL_SID(uint32_t val)
>  
>  #define REG_A6XX_GPU_GMU_CX_GMU_CX_FAL_INTF			0x000050f0
>  
> +#define REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_MSG			0x00005100
> +
> +#define REG_A6XX_GPU_GMU_CX_GMU_PWR_COL_CP_RESP			0x00005101
> +
>  #define REG_A6XX_GMU_BOOT_KMD_LM_HANDSHAKE			0x000051f0
>  
>  #define REG_A6XX_GMU_LLM_GLM_SLEEP_CTRL				0x00005157
> -- 
> 2.26.1
> 
> _______________________________________________
> Freedreno mailing list
> Freedreno@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/freedreno

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 9/9] drm/msm/a6xx: update a6xx_hw_init for A640 and A650
  2020-04-20 14:03 ` [PATCH 9/9] drm/msm/a6xx: update a6xx_hw_init for A640 and A650 Jonathan Marek
@ 2020-04-21 16:48   ` Jordan Crouse
  0 siblings, 0 replies; 18+ messages in thread
From: Jordan Crouse @ 2020-04-21 16:48 UTC (permalink / raw)
  To: Jonathan Marek
  Cc: David Airlie, freedreno, Sharat Masetty, Akhil P Oommen,
	open list:DRM DRIVER FOR MSM ADRENO GPU, open list,
	open list:DRM DRIVER FOR MSM ADRENO GPU, Sean Paul

On Mon, Apr 20, 2020 at 10:03:13AM -0400, Jonathan Marek wrote:
> Adreno 640 and 650 GPUs need some registers set differently.

> Signed-off-by: Jonathan Marek <jonathan@marek.ca>
> ---
>  drivers/gpu/drm/msm/adreno/a6xx.xml.h | 14 +++++++
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 56 ++++++++++++++++++++++-----
>  2 files changed, 61 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
> index ed78fee2a262..47840b73cdda 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx.xml.h
> +++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
> @@ -1047,6 +1047,8 @@ enum a6xx_tex_type {
>  
>  #define REG_A6XX_CP_MISC_CNTL					0x00000840
>  
> +#define REG_A6XX_CP_APRIV_CNTL					0x00000844
> +
>  #define REG_A6XX_CP_ROQ_THRESHOLDS_1				0x000008c1
>  
>  #define REG_A6XX_CP_ROQ_THRESHOLDS_2				0x000008c2
> @@ -1764,6 +1766,8 @@ static inline uint32_t A6XX_CP_PROTECT_REG_MASK_LEN(uint32_t val)
>  
>  #define REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL			0x00000010
>  
> +#define REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL			0x00000011
> +
>  #define REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL			0x0000001f
>  
>  #define REG_A6XX_RBBM_INT_CLEAR_CMD				0x00000037
> @@ -2418,6 +2422,16 @@ static inline uint32_t A6XX_UCHE_CLIENT_PF_PERFSEL(uint32_t val)
>  
>  #define REG_A6XX_TPL1_NC_MODE_CNTL				0x0000b604
>  
> +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0			0x0000b608
> +
> +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1			0x0000b609
> +
> +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2			0x0000b60a
> +
> +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3			0x0000b60b
> +
> +#define REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4			0x0000b60c
> +
>  #define REG_A6XX_TPL1_PERFCTR_TP_SEL_0				0x0000b610
>  
>  #define REG_A6XX_TPL1_PERFCTR_TP_SEL_1				0x0000b611
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index a860d4970e10..e1eb34fa3a99 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -414,7 +414,17 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
>  		a6xx_set_hwcg(gpu, true);
>  
>  	/* VBIF/GBIF start*/
> -	gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3);

Oops, this should have been changed for 618 too.  Only 630 had the VBIF
so you can invert this if statement.

> +	if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu)) {
> +		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE0, 0x00071620);
> +		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE1, 0x00071620);
> +		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE2, 0x00071620);
> +		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620);
> +		gpu_write(gpu, REG_A6XX_GBIF_QSB_SIDE3, 0x00071620);
> +		gpu_write(gpu, REG_A6XX_RBBM_GBIF_CLIENT_QOS_CNTL, 0x3);
> +	} else {
> +		gpu_write(gpu, REG_A6XX_RBBM_VBIF_CLIENT_QOS_CNTL, 0x3);
> +	}
> +
>  	if (adreno_is_a630(adreno_gpu))
>  		gpu_write(gpu, REG_A6XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009);
>  
> @@ -429,25 +439,35 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
>  	gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_LO, 0xfffff000);
>  	gpu_write(gpu, REG_A6XX_UCHE_WRITE_THRU_BASE_HI, 0x0001ffff);
>  
> -	/* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */
> -	gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO,
> -		REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000);
> +	if (!adreno_is_a650(adreno_gpu)) {
> +		/* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */
> +		gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO,
> +			REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000);
>  
> -	gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO,
> -		REG_A6XX_UCHE_GMEM_RANGE_MAX_HI,
> -		0x00100000 + adreno_gpu->gmem - 1);
> +		gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO,
> +			REG_A6XX_UCHE_GMEM_RANGE_MAX_HI,
> +			0x00100000 + adreno_gpu->gmem - 1);
> +	}
>  
>  	gpu_write(gpu, REG_A6XX_UCHE_FILTER_CNTL, 0x804);
>  	gpu_write(gpu, REG_A6XX_UCHE_CACHE_WAYS, 0x4);
>  
> -	gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0);
> +	if (adreno_is_a640(adreno_gpu) || adreno_is_a650(adreno_gpu))
> +		gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x02000140);
> +	else
> +		gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_2, 0x010000c0);
>  	gpu_write(gpu, REG_A6XX_CP_ROQ_THRESHOLDS_1, 0x8040362c);
>  
>  	/* Setting the mem pool size */
>  	gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 128);
>  
>  	/* Setting the primFifo thresholds default values */
> -	gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, (0x300 << 11));
> +	if (adreno_is_a650(adreno_gpu))
> +		gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00300000);
> +	else if (adreno_is_a640(adreno_gpu))
> +		gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, 0x00200000);
> +	else
> +		gpu_write(gpu, REG_A6XX_PC_DBG_ECO_CNTL, (0x300 << 11));
>  
>  	/* Set the AHB default slave response to "ERROR" */
>  	gpu_write(gpu, REG_A6XX_CP_AHB_CNTL, 0x1);
> @@ -471,6 +491,19 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
>  
>  	gpu_write(gpu, REG_A6XX_UCHE_CLIENT_PF, 1);
>  
> +	/* Set weights for bicubic filtering */
> +	if (adreno_is_a650(adreno_gpu)) {
> +		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_0, 0);
> +		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_1,
> +			0x3fe05ff4);
> +		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_2,
> +			0x3fa0ebee);
> +		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_3,
> +			0x3f5193ed);
> +		gpu_write(gpu, REG_A6XX_TPL1_BICUBIC_WEIGHTS_TABLE_4,
> +			0x3f0243f0);
> +	}
> +
>  	/* Protect registers from the CP */
>  	gpu_write(gpu, REG_A6XX_CP_PROTECT_CNTL, 0x00000003);
>  
> @@ -508,6 +541,11 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
>  			A6XX_PROTECT_RDONLY(0x980, 0x4));
>  	gpu_write(gpu, REG_A6XX_CP_PROTECT(25), A6XX_PROTECT_RW(0xa630, 0x0));
>  
> +	if (adreno_is_a650(adreno_gpu)) {
> +		gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL,
> +			(1 << 6) | (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1));
> +	}

Okay, so this guy is fun. With these setting enabled the ringbuffer
automatically has register protection turned off and it can access privileged
buffers without setting any special registers. This isn't something we can
immediately take advantage of but the potential is there.

> +
>  	/* Enable interrupts */
>  	gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_INT_MASK);
>  
> -- 
> 2.26.1
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 4/9] drm/msm/a6xx: HFI v2 for A640 and A650
  2020-04-21 16:30   ` Jordan Crouse
@ 2020-04-21 16:52     ` Jonathan Marek
  0 siblings, 0 replies; 18+ messages in thread
From: Jonathan Marek @ 2020-04-21 16:52 UTC (permalink / raw)
  To: freedreno, Rob Clark, Sean Paul, David Airlie, Daniel Vetter,
	Sharat Masetty, Michael J. Ruhl, Akhil P Oommen,
	open list:DRM DRIVER FOR MSM ADRENO GPU,
	open list:DRM DRIVER FOR MSM ADRENO GPU, open list

On 4/21/20 12:30 PM, Jordan Crouse wrote:
> On Mon, Apr 20, 2020 at 10:03:08AM -0400, Jonathan Marek wrote:
>> Signed-off-by: Jonathan Marek <jonathan@marek.ca>
>> ---
>>   drivers/gpu/drm/msm/adreno/a6xx_gmu.c |  68 ++++++++++++---
>>   drivers/gpu/drm/msm/adreno/a6xx_gmu.h |   7 ++
>>   drivers/gpu/drm/msm/adreno/a6xx_gpu.c |   6 +-
>>   drivers/gpu/drm/msm/adreno/a6xx_hfi.c | 117 ++++++++++++++++++++++++--
>>   drivers/gpu/drm/msm/adreno/a6xx_hfi.h |  50 ++++++++++-
>>   5 files changed, 224 insertions(+), 24 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> index c6ecb3189ec5..dc2d69837110 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
>> @@ -126,8 +126,6 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
>>   	if (ret)
>>   		dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
>>   
>> -	gmu->freq = gmu->gpu_freqs[index];
>> -
>>   	/*
>>   	 * Eventually we will want to scale the path vote with the frequency but
>>   	 * for now leave it at max so that the performance is nominal.
>> @@ -151,7 +149,12 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
>>   
>>   	gmu->current_perf_index = perf_index;
>>   
>> -	__a6xx_gmu_set_freq(gmu, perf_index);
>> +	if (gmu->legacy)
>> +		__a6xx_gmu_set_freq(gmu, perf_index);
>> +	else
>> +		a6xx_hfi_set_freq(gmu, perf_index);
> 
> Welcome to the first great GMU schism. There are going to be a lot of these if()
> statements and my guess is that it won't get any cleaner in the future.
> 
> The best option in my opinion would be to make two separate GMU implementations
> and select the probe either from the gpu list or the compatible string and use
> function pointers for the functions that are called from a6xx_gpu.c and
> a6xx_gpu_state.c.
> 
> We _could_ make the gmu->legacy thing work but if someday there is a another
> schism we would be sad that we didn't do the ground work now.
> 
> We could also do the same for HFI, but I think there is a bit less of a delta
> there and there isn't a harm in having a _v1 function or two laying around.
> 

I don't think it makes sense to have two separate GMU implementations at 
this point, most of the code is still sharable. There's "only" 10 of 
these gmu->legacy if()s in the final version, and they are very small if()s.

>> +
>> +	gmu->freq = gmu->gpu_freqs[perf_index];
>>   }
>>   
>>   unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu)
>> @@ -231,19 +234,26 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
>>   
>>   	switch (state) {
>>   	case GMU_OOB_GPU_SET:
>> -		request = GMU_OOB_GPU_SET_REQUEST;
>> -		ack = GMU_OOB_GPU_SET_ACK;
>> +		if (gmu->legacy) {
>> +			request = GMU_OOB_GPU_SET_REQUEST;
>> +			ack = GMU_OOB_GPU_SET_ACK;
>> +		} else {
>> +			request = GMU_OOB_GPU_SET_REQUEST_NEW;
>> +			ack = GMU_OOB_GPU_SET_ACK_NEW;
>> +		}
>>   		name = "GPU_SET";
>>   		break;
>>   	case GMU_OOB_BOOT_SLUMBER:
>>   		request = GMU_OOB_BOOT_SLUMBER_REQUEST;
>>   		ack = GMU_OOB_BOOT_SLUMBER_ACK;
>>   		name = "BOOT_SLUMBER";
>> +		WARN_ON(!gmu->legacy);
> 
> This is unlikely to be the case - these should only be called from within the
> GMU code and we should be able to control it.
> 

These are called from a6xx_gpu.c too, not just from within a6xx_gmu.c. 
IMO the warnings might be useful to catch errors in the future, but they 
not absolutely necessary either.

>>   		break;
>>   	case GMU_OOB_DCVS_SET:
>>   		request = GMU_OOB_DCVS_REQUEST;
>>   		ack = GMU_OOB_DCVS_ACK;
>>   		name = "GPU_DCVS";
>> +		WARN_ON(!gmu->legacy);
> 
> Same.
> 
>>   		break;
>>   	default:
>>   		return -EINVAL;
>> @@ -271,6 +281,13 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
>>   /* Clear a pending OOB state in the GMU */
>>   void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
>>   {
>> +	if (!gmu->legacy) {
>> +		WARN_ON(state != GMU_OOB_GPU_SET);
>> +		gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
>> +			1 << GMU_OOB_GPU_SET_CLEAR_NEW);
>> +		return;
>> +	}
> 
> A good example of the usefulness of per-implementation functions.
> 

I wouldn't say its a great example, the function is effectively the 
same, just with a different shift value. It was just simple enough that 
it felt better to do it this way.

>> +
>>   	switch (state) {
>>   	case GMU_OOB_GPU_SET:
>>   		gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
>> @@ -293,6 +310,9 @@ static int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
>>   	int ret;
>>   	u32 val;
>>   
>> +	if (!gmu->legacy)
>> +		return 0;
>> +
>>   	gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000);
>>   
>>   	ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, val,
>> @@ -312,6 +332,9 @@ static void a6xx_sptprac_disable(struct a6xx_gmu *gmu)
>>   	u32 val;
>>   	int ret;
>>   
>> +	if (!gmu->legacy)
>> +		return;
>> +
>>   	/* Make sure retention is on */
>>   	gmu_rmw(gmu, REG_A6XX_GPU_CC_GX_GDSCR, 0, (1 << 11));
>>   
>> @@ -355,6 +378,11 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
>>   	if (gmu->idle_level < GMU_IDLE_STATE_SPTP)
>>   		a6xx_sptprac_disable(gmu);
>>   
>> +	if (!gmu->legacy) {
>> +		ret = a6xx_hfi_send_prep_slumber(gmu);
>> +		goto out;
>> +	}
>> +
>>   	/* Tell the GMU to get ready to slumber */
>>   	gmu_write(gmu, REG_A6XX_GMU_BOOT_SLUMBER_OPTION, 1);
>>   
>> @@ -370,6 +398,7 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
>>   		}
>>   	}
>>   
>> +out:
>>   	/* Put fence into allow mode */
>>   	gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0);
>>   	return ret;
>> @@ -639,9 +668,11 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
>>   	if (ret)
>>   		return ret;
>>   
>> -	ret = a6xx_gmu_gfx_rail_on(gmu);
>> -	if (ret)
>> -		return ret;
>> +	if (gmu->legacy) {
>> +		ret = a6xx_gmu_gfx_rail_on(gmu);
>> +		if (ret)
>> +			return ret;
>> +	}
>>   
>>   	/* Enable SPTP_PC if the CPU is responsible for it */
>>   	if (gmu->idle_level < GMU_IDLE_STATE_SPTP) {
>> @@ -760,7 +791,10 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
>>   	enable_irq(gmu->hfi_irq);
>>   
>>   	/* Set the GPU to the current freq */
>> -	__a6xx_gmu_set_freq(gmu, gmu->current_perf_index);
>> +	if (gmu->legacy)
>> +		__a6xx_gmu_set_freq(gmu, gmu->current_perf_index);
>> +	else
>> +		a6xx_hfi_set_freq(gmu, gmu->current_perf_index);
>>   
>>   	/*
>>   	 * "enable" the GX power domain which won't actually do anything but it
>> @@ -1305,6 +1339,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
>>   
>>   int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>>   {
>> +	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
>>   	struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
>>   	struct platform_device *pdev = of_find_device_by_node(node);
>>   	int ret;
>> @@ -1331,16 +1366,21 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
>>   	if (ret)
>>   		goto err_put_device;
>>   
>> +	if (!adreno_is_a640(adreno_gpu) && !adreno_is_a650(adreno_gpu)) {
>> +		/* HFI v1, no sptprac */
> 
> This comment isn't accurate, 630 and 618 have sptprac, 640 and 650 do not need
> it.
> 

Right, this comment is wrong.

>> +		gmu->legacy = true;
>> +
>> +		/* Allocate memory for the GMU debug region */
>> +		gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
>> +		if (IS_ERR(gmu->debug))
>> +			goto err_memory;
>> +	}
>> +
>>   	/* Allocate memory for for the HFI queues */
>>   	gmu->hfi = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
>>   	if (IS_ERR(gmu->hfi))
>>   		goto err_memory;
>>   
>> -	/* Allocate memory for the GMU debug region */
>> -	gmu->debug = a6xx_gmu_memory_alloc(gmu, SZ_16K, 0);
>> -	if (IS_ERR(gmu->debug))
>> -		goto err_memory;
>> -
>>   	/* Map the GMU registers */
>>   	gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
>>   	if (IS_ERR(gmu->mmio))
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
>> index 2af91ed7ed0c..781714ffaa91 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
>> @@ -80,6 +80,7 @@ struct a6xx_gmu {
>>   
>>   	bool initialized;
>>   	bool hung;
>> +	bool legacy; /* a618 or a630 */
>>   };
>>   
>>   static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
>> @@ -160,10 +161,16 @@ enum a6xx_gmu_oob_state {
>>   #define GMU_OOB_GPU_SET_ACK	24
>>   #define GMU_OOB_GPU_SET_CLEAR	24
>>   
>> +#define GMU_OOB_GPU_SET_REQUEST_NEW	30
>> +#define GMU_OOB_GPU_SET_ACK_NEW		31
>> +#define GMU_OOB_GPU_SET_CLEAR_NEW	31
>> +
>>   
>>   void a6xx_hfi_init(struct a6xx_gmu *gmu);
>>   int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
>>   void a6xx_hfi_stop(struct a6xx_gmu *gmu);
>> +int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu);
>> +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index);
>>   
>>   bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
>>   bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> index 68af24150de5..a860d4970e10 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
>> @@ -566,8 +566,10 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
>>   	 */
>>   	a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
>>   
>> -	/* Take the GMU out of its special boot mode */
>> -	a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
>> +	if (a6xx_gpu->gmu.legacy) {
>> +		/* Take the GMU out of its special boot mode */
>> +		a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
>> +	}
>>   
>>   	return ret;
>>   }
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
>> index e450e0b97211..3d4b142d8fb3 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
>> @@ -17,10 +17,14 @@ static const char * const a6xx_hfi_msg_id[] = {
>>   	HFI_MSG_ID(HFI_H2F_MSG_BW_TABLE),
>>   	HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),
>>   	HFI_MSG_ID(HFI_H2F_MSG_TEST),
>> +	HFI_MSG_ID(HFI_H2F_MSG_START),
>> +	HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START),
>> +	HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE),
>> +	HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER),
>>   };
>>   
>> -static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data,
>> -		u32 dwords)
>> +static int a6xx_hfi_queue_read(struct a6xx_gmu *gmu,
>> +	struct a6xx_hfi_queue *queue, u32 *data, u32 dwords)
>>   {
>>   	struct a6xx_hfi_queue_header *header = queue->header;
>>   	u32 i, hdr, index = header->read_index;
>> @@ -48,6 +52,9 @@ static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data,
>>   		index = (index + 1) % header->size;
>>   	}
>>   
>> +	if (!gmu->legacy)
>> +		index = ALIGN(index, 4) % header->size;
>> +
>>   	header->read_index = index;
>>   	return HFI_HEADER_SIZE(hdr);
>>   }
>> @@ -73,6 +80,12 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu,
>>   		index = (index + 1) % header->size;
>>   	}
>>   
>> +	/* Cookify any non used data at the end of the write buffer */
>> +	if (!gmu->legacy) {
>> +		for (; index % 4; index = (index + 1) % header->size)
>> +			queue->data[index] = 0xfafafafa;
>> +	}
>> +
>>   	header->write_index = index;
>>   	spin_unlock(&queue->lock);
>>   
>> @@ -106,7 +119,7 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum,
>>   		struct a6xx_hfi_msg_response resp;
>>   
>>   		/* Get the next packet */
>> -		ret = a6xx_hfi_queue_read(queue, (u32 *) &resp,
>> +		ret = a6xx_hfi_queue_read(gmu, queue, (u32 *) &resp,
>>   			sizeof(resp) >> 2);
>>   
>>   		/* If the queue is empty our response never made it */
>> @@ -195,6 +208,28 @@ static int a6xx_hfi_get_fw_version(struct a6xx_gmu *gmu, u32 *version)
>>   		version, sizeof(*version));
>>   }
>>   
>> +static int a6xx_hfi_send_perf_table_v1(struct a6xx_gmu *gmu)
>> +{
>> +	struct a6xx_hfi_msg_perf_table_v1 msg = { 0 };
>> +	int i;
>> +
>> +	msg.num_gpu_levels = gmu->nr_gpu_freqs;
>> +	msg.num_gmu_levels = gmu->nr_gmu_freqs;
>> +
>> +	for (i = 0; i < gmu->nr_gpu_freqs; i++) {
>> +		msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
>> +		msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
>> +	}
>> +
>> +	for (i = 0; i < gmu->nr_gmu_freqs; i++) {
>> +		msg.cx_votes[i].vote = gmu->cx_arc_votes[i];
>> +		msg.cx_votes[i].freq = gmu->gmu_freqs[i] / 1000;
>> +	}
>> +
>> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PERF_TABLE, &msg, sizeof(msg),
>> +		NULL, 0);
>> +}
>> +
>>   static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
>>   {
>>   	struct a6xx_hfi_msg_perf_table msg = { 0 };
>> @@ -205,6 +240,7 @@ static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
>>   
>>   	for (i = 0; i < gmu->nr_gpu_freqs; i++) {
>>   		msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
>> +		msg.gx_votes[i].acd = 0xffffffff;
>>   		msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
>>   	}
>>   
>> @@ -306,7 +342,45 @@ static int a6xx_hfi_send_test(struct a6xx_gmu *gmu)
>>   		NULL, 0);
>>   }
>>   
>> -int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
>> +int a6xx_hfi_send_start(struct a6xx_gmu *gmu)
>> +{
>> +	struct a6xx_hfi_msg_start msg = { 0 };
>> +
>> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_START, &msg, sizeof(msg),
>> +		NULL, 0);
>> +}
>> +
>> +int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu)
>> +{
>> +	struct a6xx_hfi_msg_core_fw_start msg = { 0 };
>> +
>> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_CORE_FW_START, &msg,
>> +		sizeof(msg), NULL, 0);
>> +}
>> +
>> +int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index)
>> +{
>> +	struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 };
>> +
>> +	msg.ack_type = 1; /* blocking */
>> +	msg.freq = index;
>> +	msg.bw = 0; /* TODO: bus scaling */
>> +
>> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg,
>> +		sizeof(msg), NULL, 0);
>> +}
>> +
>> +int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu)
>> +{
>> +	struct a6xx_hfi_prep_slumber_cmd msg = { 0 };
>> +
>> +	/* TODO: should freq and bw fields be non-zero ? */
>> +
>> +	return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PREPARE_SLUMBER, &msg,
>> +		sizeof(msg), NULL, 0);
>> +}
>> +
>> +static int a6xx_hfi_start_v1(struct a6xx_gmu *gmu, int boot_state)
>>   {
>>   	int ret;
>>   
>> @@ -324,7 +398,7 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
>>   	 * the GMU firmware
>>   	 */
>>   
>> -	ret = a6xx_hfi_send_perf_table(gmu);
>> +	ret = a6xx_hfi_send_perf_table_v1(gmu);
>>   	if (ret)
>>   		return ret;
>>   
>> @@ -341,6 +415,37 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
>>   	return 0;
>>   }
>>   
>> +int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
>> +{
>> +	int ret;
>> +
>> +	if (gmu->legacy)
>> +		return a6xx_hfi_start_v1(gmu, boot_state);
>> +
>> +
>> +	ret = a6xx_hfi_send_perf_table(gmu);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = a6xx_hfi_send_bw_table(gmu);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = a6xx_hfi_send_core_fw_start(gmu);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/*
>> +	 * Downstream driver sends this in its "a6xx_hw_init" equivalent,
>> +	 * but seems to be no harm in sending it here
>> +	 */
>> +	ret = a6xx_hfi_send_start(gmu);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>>   void a6xx_hfi_stop(struct a6xx_gmu *gmu)
>>   {
>>   	int i;
>> @@ -415,5 +520,5 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu)
>>   	/* GMU response queue */
>>   	offset += SZ_4K;
>>   	a6xx_hfi_queue_init(&gmu->queues[1], &headers[1], hfi->virt + offset,
>> -		hfi->iova + offset, 4);
>> +		hfi->iova + offset, gmu->legacy ? 4 : 1);
>>   }
>> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
>> index 60d1319fa44f..2bd670ca42d6 100644
>> --- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
>> +++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.h
>> @@ -51,7 +51,8 @@ struct a6xx_hfi_queue {
>>   /* HFI message types */
>>   
>>   #define HFI_MSG_CMD 0
>> -#define HFI_MSG_ACK 2
>> +#define HFI_MSG_ACK 1
>> +#define HFI_MSG_ACK_V1 2
>>   
>>   #define HFI_F2H_MSG_ACK 126
>>   
>> @@ -94,7 +95,13 @@ struct perf_level {
>>   	u32 freq;
>>   };
>>   
>> -struct a6xx_hfi_msg_perf_table {
>> +struct perf_gx_level {
>> +	u32 vote;
>> +	u32 acd;
>> +	u32 freq;
>> +};
> 
> These all need to be __packed for the usual sad reasons.
> 
>> +
>> +struct a6xx_hfi_msg_perf_table_v1 {
>>   	u32 header;
>>   	u32 num_gpu_levels;
>>   	u32 num_gmu_levels;
>> @@ -103,6 +110,15 @@ struct a6xx_hfi_msg_perf_table {
>>   	struct perf_level cx_votes[4];
>>   };
>>   
>> +struct a6xx_hfi_msg_perf_table {
>> +	u32 header;
>> +	u32 num_gpu_levels;
>> +	u32 num_gmu_levels;
>> +
>> +	struct perf_gx_level gx_votes[16];
>> +	struct perf_level cx_votes[4];
>> +};
>> +
>>   #define HFI_H2F_MSG_BW_TABLE 3
>>   
>>   struct a6xx_hfi_msg_bw_table {
>> @@ -124,4 +140,34 @@ struct a6xx_hfi_msg_test {
>>   	u32 header;
>>   };
>>   
>> +#define HFI_H2F_MSG_START 10
>> +
>> +struct a6xx_hfi_msg_start {
>> +	u32 header;
>> +};
>> +
>> +#define HFI_H2F_MSG_CORE_FW_START 14
>> +
>> +struct a6xx_hfi_msg_core_fw_start {
>> +	u32 header;
>> +	u32 handle;
>> +};
>> +
>> +#define HFI_H2F_MSG_GX_BW_PERF_VOTE 30
>> +
>> +struct a6xx_hfi_gx_bw_perf_vote_cmd {
>> +	u32 header;
>> +	u32 ack_type;
>> +	u32 freq;
>> +	u32 bw;
>> +};
>> +
>> +#define HFI_H2F_MSG_PREPARE_SLUMBER 33
>> +
>> +struct a6xx_hfi_prep_slumber_cmd {
>> +	u32 header;
>> +	u32 bw;
>> +	u32 freq;
>> +};
>> +
>>   #endif
>> -- 
>> 2.26.1
>>
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2020-04-22  6:56 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20200420140313.7263-1-jonathan@marek.ca>
2020-04-20 14:03 ` [PATCH 1/9] drm/msm/adreno: add A640/A650 to gpulist Jonathan Marek
2020-04-20 14:30   ` Greg Kroah-Hartman
2020-04-20 14:03 ` [PATCH 2/9] Revert "drm/msm/a6xx: Use the DMA API for GMU memory objects" Jonathan Marek
2020-04-20 19:51   ` Bjorn Andersson
2020-04-20 19:59     ` Jonathan Marek
2020-04-20 21:16       ` Rob Clark
2020-04-20 14:03 ` [PATCH 3/9] drm/msm/a6xx: allow allocating GMU memory with a fixed address Jonathan Marek
2020-04-20 14:03 ` [PATCH 4/9] drm/msm/a6xx: HFI v2 for A640 and A650 Jonathan Marek
2020-04-21 16:30   ` Jordan Crouse
2020-04-21 16:52     ` Jonathan Marek
2020-04-20 14:03 ` [PATCH 5/9] drm/msm/a6xx: A640/A650 GMU firmware path Jonathan Marek
2020-04-20 14:03 ` [PATCH 6/9] drm/msm/a6xx: add support for A650 gmu rscc registers Jonathan Marek
2020-04-20 14:03 ` [PATCH 7/9] drm/msm/a6xx: gmu_pdc register values for A640 and A650 Jonathan Marek
2020-04-21 16:34   ` Jordan Crouse
2020-04-20 14:03 ` [PATCH 8/9] drm/msm/a6xx: enable GMU log Jonathan Marek
2020-04-21 16:38   ` [Freedreno] " Jordan Crouse
2020-04-20 14:03 ` [PATCH 9/9] drm/msm/a6xx: update a6xx_hw_init for A640 and A650 Jonathan Marek
2020-04-21 16:48   ` Jordan Crouse

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).