From 39d05e0d3af3343d3bcf09a503e950219cdca6c4 Mon Sep 17 00:00:00 2001 From: Roman Stavtsev Date: Sat, 17 Apr 2021 18:53:43 +0300 Subject: [PATCH] Baikal-M: Panfrost patch --- drivers/gpu/drm/panfrost/panfrost_gpu.c | 43 +++++++++++++++---------- drivers/gpu/drm/panfrost/panfrost_job.c | 8 +++-- drivers/gpu/drm/panfrost/panfrost_mmu.c | 32 ++++++++++++------ 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index 0d39a201c7591..72885a2492edc 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -62,7 +62,7 @@ int panfrost_gpu_soft_reset(struct panfrost_device *pfdev) gpu_write(pfdev, GPU_CMD, GPU_CMD_SOFT_RESET); ret = readl_relaxed_poll_timeout(pfdev->iomem + GPU_INT_RAWSTAT, - val, val & GPU_IRQ_RESET_COMPLETED, 100, 10000); + val, val & GPU_IRQ_RESET_COMPLETED, 5, 10000); if (ret) { dev_err(pfdev->dev, "gpu soft reset timed out\n"); @@ -313,26 +313,34 @@ static void panfrost_gpu_init_features(struct panfrost_device *pfdev) void panfrost_gpu_power_on(struct panfrost_device *pfdev) { int ret; - u32 val; + ktime_t timeout; panfrost_gpu_init_quirks(pfdev); /* Just turn on everything for now */ gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present); - ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO, - val, val == pfdev->features.l2_present, 100, 1000); - gpu_write(pfdev, STACK_PWRON_LO, pfdev->features.stack_present); - ret |= readl_relaxed_poll_timeout(pfdev->iomem + STACK_READY_LO, - val, val == pfdev->features.stack_present, 100, 1000); - gpu_write(pfdev, SHADER_PWRON_LO, pfdev->features.shader_present); - ret |= readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO, - val, val == pfdev->features.shader_present, 100, 1000); - gpu_write(pfdev, TILER_PWRON_LO, pfdev->features.tiler_present); - ret |= readl_relaxed_poll_timeout(pfdev->iomem + TILER_READY_LO, - val, val == pfdev->features.tiler_present, 100, 1000); + + timeout = ktime_add_us(ktime_get(), 1000); + ret = 0; + for (;;) { + if (gpu_read(pfdev, L2_READY_LO) == + pfdev->features.l2_present && + gpu_read(pfdev, STACK_READY_LO) == + pfdev->features.stack_present && + gpu_read(pfdev, SHADER_READY_LO) == + pfdev->features.shader_present && + gpu_read(pfdev, TILER_READY_LO) == + pfdev->features.tiler_present) + break; + if (ktime_compare(ktime_get(), timeout) > 0) { + ret = 1; + break; + } + usleep_range(3, 5); + } if (ret) dev_err(pfdev->dev, "error powering up gpu"); @@ -340,10 +348,11 @@ void panfrost_gpu_power_on(struct panfrost_device *pfdev) void panfrost_gpu_power_off(struct panfrost_device *pfdev) { - gpu_write(pfdev, TILER_PWROFF_LO, 0); - gpu_write(pfdev, SHADER_PWROFF_LO, 0); - gpu_write(pfdev, STACK_PWROFF_LO, 0); - gpu_write(pfdev, L2_PWROFF_LO, 0); + dev_dbg(pfdev->dev, "gpu_power_off...\n"); + gpu_write(pfdev, TILER_PWROFF_LO, pfdev->features.tiler_present); + gpu_write(pfdev, SHADER_PWROFF_LO, pfdev->features.shader_present); + gpu_write(pfdev, STACK_PWROFF_LO, pfdev->features.stack_present); + gpu_write(pfdev, L2_PWROFF_LO, pfdev->features.l2_present); } int panfrost_gpu_init(struct panfrost_device *pfdev) diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index 9f770d4546848..e80bb921aa4ba 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -133,6 +133,8 @@ static void panfrost_job_write_affinity(struct panfrost_device *pfdev, * multiple (2) coherent core groups */ affinity = pfdev->features.shader_present; + if (panfrost_model_eq(pfdev, 0x620) && js == 1) + affinity &= 0xf; job_write(pfdev, JS_AFFINITY_NEXT_LO(js), affinity & 0xFFFFFFFF); job_write(pfdev, JS_AFFINITY_NEXT_HI(js), affinity >> 32); @@ -181,7 +183,7 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js) job_write(pfdev, JS_FLUSH_ID_NEXT(js), job->flush_id); /* GO ! */ - dev_dbg(pfdev->dev, "JS: Submitting atom %p to js[%d] with head=0x%llx", + dev_dbg(pfdev->dev, "JS: Submitting atom %px to js[%d] with head=0x%llx", job, js, jc_head); job_write(pfdev, JS_COMMAND_NEXT(js), JS_COMMAND_START); @@ -389,7 +391,7 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job) if (dma_fence_is_signaled(job->done_fence)) return; - dev_err(pfdev->dev, "gpu sched timeout, js=%d, config=0x%x, status=0x%x, head=0x%x, tail=0x%x, sched_job=%p", + dev_err(pfdev->dev, "gpu sched timeout, js=%d, config=0x%x, status=0x%x, head=0x%x, tail=0x%x, sched_job=%px", js, job_read(pfdev, JS_CONFIG(js)), job_read(pfdev, JS_STATUS(js)), @@ -403,7 +405,7 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job) for (i = 0; i < NUM_JOB_SLOTS; i++) { struct drm_gpu_scheduler *sched = &pfdev->js->queue[i].sched; - drm_sched_stop(sched, sched_job); + drm_sched_stop(sched, pfdev->jobs[i] ? &pfdev->jobs[i]->base : NULL); if (js != i) /* Ensure any timeouts on other slots have finished */ cancel_delayed_work_sync(&sched->work_tdr); diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 3dc9b30a64b01..f04dd9955cff6 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -31,7 +31,7 @@ static int wait_ready(struct panfrost_device *pfdev, u32 as_nr) /* Wait for the MMU status to indicate there is no active command, in * case one is pending. */ ret = readl_relaxed_poll_timeout_atomic(pfdev->iomem + AS_STATUS(as_nr), - val, !(val & AS_STATUS_AS_ACTIVE), 10, 1000); + val, !(val & AS_STATUS_AS_ACTIVE), 3, 1000); if (ret) dev_err(pfdev->dev, "AS_ACTIVE bit stuck\n"); @@ -64,13 +64,21 @@ static void lock_region(struct panfrost_device *pfdev, u32 as_nr, * results in the range (11 .. 42) */ - size = round_up(size, PAGE_SIZE); - - region_width = 10 + fls(size >> PAGE_SHIFT); - if ((size >> PAGE_SHIFT) != (1ul << (region_width - 11))) { - /* not pow2, so must go up to the next pow2 */ - region_width += 1; + if (size & ~PAGE_MASK) + size = (size >> PAGE_SHIFT) + 1; + else + size = size >> PAGE_SHIFT; + region_width = 10; + if (size > 0x80000000) { + if (size & 0xffffffff) + size = (size >> 32) + 1; + else + size = size >> 32; + region_width += 32; } + region_width += fls(size); + if (size != (1ul << ((region_width - 11) & 0x1f))) + region_width++; region |= region_width; /* Lock the region that needs to be updated */ @@ -115,7 +123,7 @@ static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_m u64 transtab = cfg->arm_mali_lpae_cfg.transtab; u64 memattr = cfg->arm_mali_lpae_cfg.memattr; - mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0UL, AS_COMMAND_FLUSH_MEM); + mmu_hw_do_operation_locked(pfdev, as_nr, 0, 1ULL << 48, AS_COMMAND_FLUSH_MEM); mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), transtab & 0xffffffffUL); mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), transtab >> 32); @@ -123,6 +131,10 @@ static void panfrost_mmu_enable(struct panfrost_device *pfdev, struct panfrost_m /* Need to revisit mem attrs. * NC is the default, Mali driver is inner WT. */ + if (pfdev->features.id == 0x620) { + memattr &= ~0xf0f0f0ULL; + memattr |= 0x404040; + } mmu_write(pfdev, AS_MEMATTR_LO(as_nr), memattr & 0xffffffffUL); mmu_write(pfdev, AS_MEMATTR_HI(as_nr), memattr >> 32); @@ -186,7 +198,7 @@ u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu) atomic_set(&mmu->as_count, 1); list_add(&mmu->list, &pfdev->as_lru_list); - dev_dbg(pfdev->dev, "Assigned AS%d to mmu %p, alloc_mask=%lx", as, mmu, pfdev->as_alloc_mask); + dev_dbg(pfdev->dev, "Assigned AS%d to mmu %px, alloc_mask=%lx", as, mmu, pfdev->as_alloc_mask); panfrost_mmu_enable(pfdev, mmu); @@ -287,6 +299,8 @@ int panfrost_mmu_map(struct panfrost_gem_mapping *mapping) if (bo->noexec) prot |= IOMMU_NOEXEC; + if (bo->is_heap) + prot |= IOMMU_CACHE; sgt = drm_gem_shmem_get_pages_sgt(obj); if (WARN_ON(IS_ERR(sgt)))