File Index
Files and directories
Sign in
FILE

a2xx_gpummu.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2018 The Linux Foundation. All rights reserved. */
  3
  4#include <linux/dma-mapping.h>
  5
  6#include "msm_drv.h"
  7#include "msm_mmu.h"
  8
  9#include "adreno_gpu.h"
 10#include "a2xx_gpu.h"
 11
 12#include "a2xx.xml.h"
 13
 14struct a2xx_gpummu {
 15	struct msm_mmu base;
 16	struct msm_gpu *gpu;
 17	dma_addr_t pt_base;
 18	uint32_t *table;
 19};
 20#define to_a2xx_gpummu(x) container_of(x, struct a2xx_gpummu, base)
 21
 22#define GPUMMU_VA_START SZ_16M
 23#define GPUMMU_VA_RANGE (0xfff * SZ_64K)
 24#define GPUMMU_PAGE_SIZE SZ_4K
 25#define TABLE_SIZE (sizeof(uint32_t) * GPUMMU_VA_RANGE / GPUMMU_PAGE_SIZE)
 26
 27static void a2xx_gpummu_detach(struct msm_mmu *mmu)
 28{
 29}
 30
 31static int a2xx_gpummu_map(struct msm_mmu *mmu, uint64_t iova,
 32			   struct sg_table *sgt, size_t off, size_t len,
 33			   int prot)
 34{
 35	struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu);
 36	unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE;
 37	struct sg_dma_page_iter dma_iter;
 38	unsigned prot_bits = 0;
 39
 40	WARN_ON(off != 0);
 41
 42	if (prot & IOMMU_WRITE)
 43		prot_bits |= 1;
 44	if (prot & IOMMU_READ)
 45		prot_bits |= 2;
 46
 47	for_each_sgtable_dma_page(sgt, &dma_iter, 0) {
 48		dma_addr_t addr = sg_page_iter_dma_address(&dma_iter);
 49		int i;
 50
 51		for (i = 0; i < PAGE_SIZE; i += GPUMMU_PAGE_SIZE)
 52			gpummu->table[idx++] = (addr + i) | prot_bits;
 53	}
 54
 55	/* we can improve by deferring flush for multiple map() */
 56	gpu_write(gpummu->gpu, REG_A2XX_MH_MMU_INVALIDATE,
 57		A2XX_MH_MMU_INVALIDATE_INVALIDATE_ALL |
 58		A2XX_MH_MMU_INVALIDATE_INVALIDATE_TC);
 59	return 0;
 60}
 61
 62static int a2xx_gpummu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len)
 63{
 64	struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu);
 65	unsigned idx = (iova - GPUMMU_VA_START) / GPUMMU_PAGE_SIZE;
 66	unsigned i;
 67
 68	for (i = 0; i < len / GPUMMU_PAGE_SIZE; i++, idx++)
 69                gpummu->table[idx] = 0;
 70
 71	gpu_write(gpummu->gpu, REG_A2XX_MH_MMU_INVALIDATE,
 72		A2XX_MH_MMU_INVALIDATE_INVALIDATE_ALL |
 73		A2XX_MH_MMU_INVALIDATE_INVALIDATE_TC);
 74	return 0;
 75}
 76
 77static void a2xx_gpummu_destroy(struct msm_mmu *mmu)
 78{
 79	struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu);
 80
 81	dma_free_attrs(mmu->dev, TABLE_SIZE + 32, gpummu->table, gpummu->pt_base,
 82		DMA_ATTR_FORCE_CONTIGUOUS);
 83
 84	kfree(gpummu);
 85}
 86
 87static const struct msm_mmu_funcs funcs = {
 88		.detach = a2xx_gpummu_detach,
 89		.map = a2xx_gpummu_map,
 90		.unmap = a2xx_gpummu_unmap,
 91		.destroy = a2xx_gpummu_destroy,
 92};
 93
 94struct msm_mmu *a2xx_gpummu_new(struct device *dev, struct msm_gpu *gpu)
 95{
 96	struct a2xx_gpummu *gpummu;
 97
 98	gpummu = kzalloc(sizeof(*gpummu), GFP_KERNEL);
 99	if (!gpummu)
100		return ERR_PTR(-ENOMEM);
101
102	gpummu->table = dma_alloc_attrs(dev, TABLE_SIZE + 32, &gpummu->pt_base,
103		GFP_KERNEL | __GFP_ZERO, DMA_ATTR_FORCE_CONTIGUOUS);
104	if (!gpummu->table) {
105		kfree(gpummu);
106		return ERR_PTR(-ENOMEM);
107	}
108
109	gpummu->gpu = gpu;
110	msm_mmu_init(&gpummu->base, dev, &funcs, MSM_MMU_GPUMMU);
111
112	return &gpummu->base;
113}
114
115void a2xx_gpummu_params(struct msm_mmu *mmu, dma_addr_t *pt_base,
116		dma_addr_t *tran_error)
117{
118	dma_addr_t base = to_a2xx_gpummu(mmu)->pt_base;
119
120	*pt_base = base;
121	*tran_error = base + TABLE_SIZE; /* 32-byte aligned */
122}
~/ Read-only file preview.