drm/msm: implement a2xx mmu

A2XX has its own very simple MMU.

Added a msm_use_mmu() function because we can't rely on iommu_present to
decide to use MMU or not.

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
Jonathan Marek
2018-11-14 17:08:04 -05:00
committed by Rob Clark
parent d1d9d0e172
commit c2052a4e5c
11 changed files with 240 additions and 18 deletions

View File

@@ -2,6 +2,8 @@
/* Copyright (c) 2018 The Linux Foundation. All rights reserved. */
#include "a2xx_gpu.h"
#include "msm_gem.h"
#include "msm_mmu.h"
extern bool hang_debug;
@@ -58,9 +60,12 @@ static bool a2xx_me_init(struct msm_gpu *gpu)
static int a2xx_hw_init(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
dma_addr_t pt_base, tran_error;
uint32_t *ptr, len;
int i, ret;
msm_gpummu_params(gpu->aspace->mmu, &pt_base, &tran_error);
DBG("%s", gpu->name);
/* halt ME to avoid ucode upload issues on a20x */
@@ -80,9 +85,34 @@ static int a2xx_hw_init(struct msm_gpu *gpu)
/* note: kgsl uses 0x0000ffff for a20x */
gpu_write(gpu, REG_A2XX_RBBM_CNTL, 0x00004442);
gpu_write(gpu, REG_A2XX_MH_MMU_CONFIG, 0);
gpu_write(gpu, REG_A2XX_MH_MMU_MPU_BASE, 0);
/* MPU: physical range */
gpu_write(gpu, REG_A2XX_MH_MMU_MPU_BASE, 0x00000000);
gpu_write(gpu, REG_A2XX_MH_MMU_MPU_END, 0xfffff000);
gpu_write(gpu, REG_A2XX_MH_MMU_CONFIG, A2XX_MH_MMU_CONFIG_MMU_ENABLE |
A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR(BEH_TRAN_RNG) |
A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR(BEH_TRAN_RNG));
/* same as parameters in adreno_gpu */
gpu_write(gpu, REG_A2XX_MH_MMU_VA_RANGE, SZ_16M |
A2XX_MH_MMU_VA_RANGE_NUM_64KB_REGIONS(0xfff));
gpu_write(gpu, REG_A2XX_MH_MMU_PT_BASE, pt_base);
gpu_write(gpu, REG_A2XX_MH_MMU_TRAN_ERROR, tran_error);
gpu_write(gpu, REG_A2XX_MH_MMU_INVALIDATE,
A2XX_MH_MMU_INVALIDATE_INVALIDATE_ALL |
A2XX_MH_MMU_INVALIDATE_INVALIDATE_TC);
gpu_write(gpu, REG_A2XX_MH_ARBITER_CONFIG,
A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT(16) |
A2XX_MH_ARBITER_CONFIG_L1_ARB_ENABLE |
@@ -109,9 +139,21 @@ static int a2xx_hw_init(struct msm_gpu *gpu)
/* note: gsl doesn't set this */
gpu_write(gpu, REG_A2XX_RBBM_DEBUG, 0x00080000);
gpu_write(gpu, REG_A2XX_RBBM_INT_CNTL, 0);
gpu_write(gpu, REG_AXXX_CP_INT_CNTL, 0x80000000); /* RB INT */
gpu_write(gpu, REG_A2XX_RBBM_INT_CNTL,
A2XX_RBBM_INT_CNTL_RDERR_INT_MASK);
gpu_write(gpu, REG_AXXX_CP_INT_CNTL,
AXXX_CP_INT_CNTL_T0_PACKET_IN_IB_MASK |
AXXX_CP_INT_CNTL_OPCODE_ERROR_MASK |
AXXX_CP_INT_CNTL_PROTECTED_MODE_ERROR_MASK |
AXXX_CP_INT_CNTL_RESERVED_BIT_ERROR_MASK |
AXXX_CP_INT_CNTL_IB_ERROR_MASK |
AXXX_CP_INT_CNTL_IB1_INT_MASK |
AXXX_CP_INT_CNTL_RB_INT_MASK);
gpu_write(gpu, REG_A2XX_SQ_INT_CNTL, 0);
gpu_write(gpu, REG_A2XX_MH_INTERRUPT_MASK,
A2XX_MH_INTERRUPT_MASK_AXI_READ_ERROR |
A2XX_MH_INTERRUPT_MASK_AXI_WRITE_ERROR |
A2XX_MH_INTERRUPT_MASK_MMU_PAGE_FAULT);
for (i = 3; i <= 5; i++)
if ((SZ_16K << i) == adreno_gpu->gmem)

View File

@@ -307,6 +307,7 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
static struct adreno_platform_config config = {};
const struct adreno_info *info;
struct drm_device *drm = dev_get_drvdata(master);
struct msm_drm_private *priv = drm->dev_private;
struct msm_gpu *gpu;
int ret;
@@ -329,6 +330,8 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
DBG("Found GPU: %u.%u.%u.%u", config.rev.core, config.rev.major,
config.rev.minor, config.rev.patchid);
priv->is_a2xx = config.rev.core == 2;
gpu = info->init(drm);
if (IS_ERR(gpu)) {
dev_warn(drm->dev, "failed to load adreno gpu\n");

View File

@@ -769,6 +769,9 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
adreno_gpu_config.va_start = SZ_16M;
adreno_gpu_config.va_end = 0xffffffff;
/* maximum range of a2xx mmu */
if (adreno_is_a2xx(adreno_gpu))
adreno_gpu_config.va_end = SZ_16M + 0xfff * SZ_64K;
adreno_gpu_config.nr_rings = nr_rings;