/* Gracefully try to shut down the GMU and by extension the GPU */ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) { struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct msm_gpu *gpu = &adreno_gpu->base; u32 val; /* * The GMU may still be in slumber unless the GPU started so check and * skip putting it back into slumber if so */ val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE); if (val != 0xf) { int ret = a6xx_gmu_wait_for_idle(gmu); /* If the GMU isn't responding assume it is hung */ if (ret) { a6xx_gmu_force_off(gmu); return; } /* Clear the VBIF pipe before shutting down */ gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf); spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) & 0xf) == 0xf); gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0); /* tell the GMU we want to slumber */ a6xx_gmu_notify_slumber(gmu); ret = gmu_poll_timeout(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val, !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB), 100, 10000); /* * Let the user know we failed to slumber but don't worry too * much because we are powering down anyway */ if (ret) DRM_DEV_ERROR(gmu->dev, "Unable to slumber GMU: status = 0%x/0%x\n", gmu_read(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS), gmu_read(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2)); } /* Turn off HFI */ a6xx_hfi_stop(gmu); /* Stop the interrupts and mask the hardware */ a6xx_gmu_irq_disable(gmu); /* Tell RPMh to power off the GPU */ a6xx_rpmh_stop(gmu); }
static void a4xx_idle(struct msm_gpu *gpu) { /* wait for ringbuffer to drain: */ adreno_idle(gpu); /* then wait for GPU to finish: */ if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) & A4XX_RBBM_STATUS_GPU_BUSY))) DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); /* TODO maybe we need to reset GPU here to recover from hang? */ }
bool adreno_idle(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); uint32_t wptr = get_wptr(gpu->rb); /* wait for CP to drain ringbuffer: */ if (!spin_until(get_rptr(adreno_gpu) == wptr)) return true; /* TODO maybe we need to reset GPU here to recover from hang? */ DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name); return false; }
void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) { if (spin_until(ring_freewords(gpu) >= ndwords)) DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name); }
/* Wait for the GMU to get to its most idle state */ int a6xx_gmu_wait_for_idle(struct a6xx_gmu *gmu) { return spin_until(a6xx_gmu_check_idle_level(gmu)); }
/* Wait for the GMU to get to its most idle state */ int a6xx_gmu_wait_for_idle(struct a6xx_gpu *a6xx_gpu) { struct a6xx_gmu *gmu = &a6xx_gpu->gmu; return spin_until(a6xx_gmu_check_idle_level(gmu)); }