18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright 2019 Collabora Ltd */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <drm/drm_file.h> 58c2ecf20Sopenharmony_ci#include <drm/drm_gem_shmem_helper.h> 68c2ecf20Sopenharmony_ci#include <drm/panfrost_drm.h> 78c2ecf20Sopenharmony_ci#include <linux/completion.h> 88c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 98c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 108c2ecf20Sopenharmony_ci#include <linux/slab.h> 118c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "panfrost_device.h" 148c2ecf20Sopenharmony_ci#include "panfrost_features.h" 158c2ecf20Sopenharmony_ci#include "panfrost_gem.h" 168c2ecf20Sopenharmony_ci#include "panfrost_issues.h" 178c2ecf20Sopenharmony_ci#include "panfrost_job.h" 188c2ecf20Sopenharmony_ci#include "panfrost_mmu.h" 198c2ecf20Sopenharmony_ci#include "panfrost_perfcnt.h" 208c2ecf20Sopenharmony_ci#include "panfrost_regs.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define COUNTERS_PER_BLOCK 64 238c2ecf20Sopenharmony_ci#define BYTES_PER_COUNTER 4 248c2ecf20Sopenharmony_ci#define BLOCKS_PER_COREGROUP 8 258c2ecf20Sopenharmony_ci#define V4_SHADERS_PER_COREGROUP 4 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct panfrost_perfcnt { 288c2ecf20Sopenharmony_ci struct panfrost_gem_mapping *mapping; 298c2ecf20Sopenharmony_ci size_t bosize; 308c2ecf20Sopenharmony_ci void *buf; 318c2ecf20Sopenharmony_ci struct panfrost_file_priv *user; 328c2ecf20Sopenharmony_ci struct mutex lock; 338c2ecf20Sopenharmony_ci struct completion dump_comp; 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_civoid panfrost_perfcnt_clean_cache_done(struct panfrost_device *pfdev) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci complete(&pfdev->perfcnt->dump_comp); 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_civoid panfrost_perfcnt_sample_done(struct panfrost_device *pfdev) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_CMD, GPU_CMD_CLEAN_CACHES); 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic int panfrost_perfcnt_dump_locked(struct panfrost_device *pfdev) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci u64 gpuva; 498c2ecf20Sopenharmony_ci int ret; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci reinit_completion(&pfdev->perfcnt->dump_comp); 528c2ecf20Sopenharmony_ci gpuva = pfdev->perfcnt->mapping->mmnode.start << PAGE_SHIFT; 538c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PERFCNT_BASE_LO, gpuva); 548c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PERFCNT_BASE_HI, gpuva >> 32); 558c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_INT_CLEAR, 568c2ecf20Sopenharmony_ci GPU_IRQ_CLEAN_CACHES_COMPLETED | 578c2ecf20Sopenharmony_ci GPU_IRQ_PERFCNT_SAMPLE_COMPLETED); 588c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_CMD, GPU_CMD_PERFCNT_SAMPLE); 598c2ecf20Sopenharmony_ci ret = wait_for_completion_interruptible_timeout(&pfdev->perfcnt->dump_comp, 608c2ecf20Sopenharmony_ci msecs_to_jiffies(1000)); 618c2ecf20Sopenharmony_ci if (!ret) 628c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 638c2ecf20Sopenharmony_ci else if (ret > 0) 648c2ecf20Sopenharmony_ci ret = 0; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci return ret; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev, 708c2ecf20Sopenharmony_ci struct drm_file *file_priv, 718c2ecf20Sopenharmony_ci unsigned int counterset) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci struct panfrost_file_priv *user = file_priv->driver_priv; 748c2ecf20Sopenharmony_ci struct panfrost_perfcnt *perfcnt = pfdev->perfcnt; 758c2ecf20Sopenharmony_ci struct drm_gem_shmem_object *bo; 768c2ecf20Sopenharmony_ci u32 cfg, as; 778c2ecf20Sopenharmony_ci int ret; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (user == perfcnt->user) 808c2ecf20Sopenharmony_ci return 0; 818c2ecf20Sopenharmony_ci else if (perfcnt->user) 828c2ecf20Sopenharmony_ci return -EBUSY; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci ret = pm_runtime_get_sync(pfdev->dev); 858c2ecf20Sopenharmony_ci if (ret < 0) 868c2ecf20Sopenharmony_ci goto err_put_pm; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci bo = drm_gem_shmem_create(pfdev->ddev, perfcnt->bosize); 898c2ecf20Sopenharmony_ci if (IS_ERR(bo)) { 908c2ecf20Sopenharmony_ci ret = PTR_ERR(bo); 918c2ecf20Sopenharmony_ci goto err_put_pm; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* Map the perfcnt buf in the address space attached to file_priv. */ 958c2ecf20Sopenharmony_ci ret = panfrost_gem_open(&bo->base, file_priv); 968c2ecf20Sopenharmony_ci if (ret) 978c2ecf20Sopenharmony_ci goto err_put_bo; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci perfcnt->mapping = panfrost_gem_mapping_get(to_panfrost_bo(&bo->base), 1008c2ecf20Sopenharmony_ci user); 1018c2ecf20Sopenharmony_ci if (!perfcnt->mapping) { 1028c2ecf20Sopenharmony_ci ret = -EINVAL; 1038c2ecf20Sopenharmony_ci goto err_close_bo; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci perfcnt->buf = drm_gem_shmem_vmap(&bo->base); 1078c2ecf20Sopenharmony_ci if (IS_ERR(perfcnt->buf)) { 1088c2ecf20Sopenharmony_ci ret = PTR_ERR(perfcnt->buf); 1098c2ecf20Sopenharmony_ci goto err_put_mapping; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* 1138c2ecf20Sopenharmony_ci * Invalidate the cache and clear the counters to start from a fresh 1148c2ecf20Sopenharmony_ci * state. 1158c2ecf20Sopenharmony_ci */ 1168c2ecf20Sopenharmony_ci reinit_completion(&pfdev->perfcnt->dump_comp); 1178c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_INT_CLEAR, 1188c2ecf20Sopenharmony_ci GPU_IRQ_CLEAN_CACHES_COMPLETED | 1198c2ecf20Sopenharmony_ci GPU_IRQ_PERFCNT_SAMPLE_COMPLETED); 1208c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_CMD, GPU_CMD_PERFCNT_CLEAR); 1218c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_CMD, GPU_CMD_CLEAN_INV_CACHES); 1228c2ecf20Sopenharmony_ci ret = wait_for_completion_timeout(&pfdev->perfcnt->dump_comp, 1238c2ecf20Sopenharmony_ci msecs_to_jiffies(1000)); 1248c2ecf20Sopenharmony_ci if (!ret) { 1258c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 1268c2ecf20Sopenharmony_ci goto err_vunmap; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci perfcnt->user = user; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci as = panfrost_mmu_as_get(pfdev, perfcnt->mapping->mmu); 1328c2ecf20Sopenharmony_ci cfg = GPU_PERFCNT_CFG_AS(as) | 1338c2ecf20Sopenharmony_ci GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_MANUAL); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci /* 1368c2ecf20Sopenharmony_ci * Bifrost GPUs have 2 set of counters, but we're only interested by 1378c2ecf20Sopenharmony_ci * the first one for now. 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci if (panfrost_model_is_bifrost(pfdev)) 1408c2ecf20Sopenharmony_ci cfg |= GPU_PERFCNT_CFG_SETSEL(counterset); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_JM_EN, 0xffffffff); 1438c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_SHADER_EN, 0xffffffff); 1448c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_MMU_L2_EN, 0xffffffff); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* 1478c2ecf20Sopenharmony_ci * Due to PRLAM-8186 we need to disable the Tiler before we enable HW 1488c2ecf20Sopenharmony_ci * counters. 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_ci if (panfrost_has_hw_issue(pfdev, HW_ISSUE_8186)) 1518c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_TILER_EN, 0); 1528c2ecf20Sopenharmony_ci else 1538c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_TILER_EN, 0xffffffff); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PERFCNT_CFG, cfg); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (panfrost_has_hw_issue(pfdev, HW_ISSUE_8186)) 1588c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_TILER_EN, 0xffffffff); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* The BO ref is retained by the mapping. */ 1618c2ecf20Sopenharmony_ci drm_gem_object_put(&bo->base); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci return 0; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cierr_vunmap: 1668c2ecf20Sopenharmony_ci drm_gem_shmem_vunmap(&bo->base, perfcnt->buf); 1678c2ecf20Sopenharmony_cierr_put_mapping: 1688c2ecf20Sopenharmony_ci panfrost_gem_mapping_put(perfcnt->mapping); 1698c2ecf20Sopenharmony_cierr_close_bo: 1708c2ecf20Sopenharmony_ci panfrost_gem_close(&bo->base, file_priv); 1718c2ecf20Sopenharmony_cierr_put_bo: 1728c2ecf20Sopenharmony_ci drm_gem_object_put(&bo->base); 1738c2ecf20Sopenharmony_cierr_put_pm: 1748c2ecf20Sopenharmony_ci pm_runtime_put(pfdev->dev); 1758c2ecf20Sopenharmony_ci return ret; 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev, 1798c2ecf20Sopenharmony_ci struct drm_file *file_priv) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct panfrost_file_priv *user = file_priv->driver_priv; 1828c2ecf20Sopenharmony_ci struct panfrost_perfcnt *perfcnt = pfdev->perfcnt; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (user != perfcnt->user) 1858c2ecf20Sopenharmony_ci return -EINVAL; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_JM_EN, 0x0); 1888c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_SHADER_EN, 0x0); 1898c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_MMU_L2_EN, 0x0); 1908c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_TILER_EN, 0); 1918c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PERFCNT_CFG, 1928c2ecf20Sopenharmony_ci GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_OFF)); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci perfcnt->user = NULL; 1958c2ecf20Sopenharmony_ci drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base.base, perfcnt->buf); 1968c2ecf20Sopenharmony_ci perfcnt->buf = NULL; 1978c2ecf20Sopenharmony_ci panfrost_gem_close(&perfcnt->mapping->obj->base.base, file_priv); 1988c2ecf20Sopenharmony_ci panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu); 1998c2ecf20Sopenharmony_ci panfrost_gem_mapping_put(perfcnt->mapping); 2008c2ecf20Sopenharmony_ci perfcnt->mapping = NULL; 2018c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(pfdev->dev); 2028c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(pfdev->dev); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci return 0; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ciint panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data, 2088c2ecf20Sopenharmony_ci struct drm_file *file_priv) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci struct panfrost_device *pfdev = dev->dev_private; 2118c2ecf20Sopenharmony_ci struct panfrost_perfcnt *perfcnt = pfdev->perfcnt; 2128c2ecf20Sopenharmony_ci struct drm_panfrost_perfcnt_enable *req = data; 2138c2ecf20Sopenharmony_ci int ret; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci ret = panfrost_unstable_ioctl_check(); 2168c2ecf20Sopenharmony_ci if (ret) 2178c2ecf20Sopenharmony_ci return ret; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* Only Bifrost GPUs have 2 set of counters. */ 2208c2ecf20Sopenharmony_ci if (req->counterset > (panfrost_model_is_bifrost(pfdev) ? 1 : 0)) 2218c2ecf20Sopenharmony_ci return -EINVAL; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci mutex_lock(&perfcnt->lock); 2248c2ecf20Sopenharmony_ci if (req->enable) 2258c2ecf20Sopenharmony_ci ret = panfrost_perfcnt_enable_locked(pfdev, file_priv, 2268c2ecf20Sopenharmony_ci req->counterset); 2278c2ecf20Sopenharmony_ci else 2288c2ecf20Sopenharmony_ci ret = panfrost_perfcnt_disable_locked(pfdev, file_priv); 2298c2ecf20Sopenharmony_ci mutex_unlock(&perfcnt->lock); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci return ret; 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ciint panfrost_ioctl_perfcnt_dump(struct drm_device *dev, void *data, 2358c2ecf20Sopenharmony_ci struct drm_file *file_priv) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci struct panfrost_device *pfdev = dev->dev_private; 2388c2ecf20Sopenharmony_ci struct panfrost_perfcnt *perfcnt = pfdev->perfcnt; 2398c2ecf20Sopenharmony_ci struct drm_panfrost_perfcnt_dump *req = data; 2408c2ecf20Sopenharmony_ci void __user *user_ptr = (void __user *)(uintptr_t)req->buf_ptr; 2418c2ecf20Sopenharmony_ci int ret; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci ret = panfrost_unstable_ioctl_check(); 2448c2ecf20Sopenharmony_ci if (ret) 2458c2ecf20Sopenharmony_ci return ret; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci mutex_lock(&perfcnt->lock); 2488c2ecf20Sopenharmony_ci if (perfcnt->user != file_priv->driver_priv) { 2498c2ecf20Sopenharmony_ci ret = -EINVAL; 2508c2ecf20Sopenharmony_ci goto out; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci ret = panfrost_perfcnt_dump_locked(pfdev); 2548c2ecf20Sopenharmony_ci if (ret) 2558c2ecf20Sopenharmony_ci goto out; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (copy_to_user(user_ptr, perfcnt->buf, perfcnt->bosize)) 2588c2ecf20Sopenharmony_ci ret = -EFAULT; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ciout: 2618c2ecf20Sopenharmony_ci mutex_unlock(&perfcnt->lock); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci return ret; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_civoid panfrost_perfcnt_close(struct drm_file *file_priv) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct panfrost_file_priv *pfile = file_priv->driver_priv; 2698c2ecf20Sopenharmony_ci struct panfrost_device *pfdev = pfile->pfdev; 2708c2ecf20Sopenharmony_ci struct panfrost_perfcnt *perfcnt = pfdev->perfcnt; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci pm_runtime_get_sync(pfdev->dev); 2738c2ecf20Sopenharmony_ci mutex_lock(&perfcnt->lock); 2748c2ecf20Sopenharmony_ci if (perfcnt->user == pfile) 2758c2ecf20Sopenharmony_ci panfrost_perfcnt_disable_locked(pfdev, file_priv); 2768c2ecf20Sopenharmony_ci mutex_unlock(&perfcnt->lock); 2778c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(pfdev->dev); 2788c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(pfdev->dev); 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ciint panfrost_perfcnt_init(struct panfrost_device *pfdev) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci struct panfrost_perfcnt *perfcnt; 2848c2ecf20Sopenharmony_ci size_t size; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci if (panfrost_has_hw_feature(pfdev, HW_FEATURE_V4)) { 2878c2ecf20Sopenharmony_ci unsigned int ncoregroups; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci ncoregroups = hweight64(pfdev->features.l2_present); 2908c2ecf20Sopenharmony_ci size = ncoregroups * BLOCKS_PER_COREGROUP * 2918c2ecf20Sopenharmony_ci COUNTERS_PER_BLOCK * BYTES_PER_COUNTER; 2928c2ecf20Sopenharmony_ci } else { 2938c2ecf20Sopenharmony_ci unsigned int nl2c, ncores; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* 2968c2ecf20Sopenharmony_ci * TODO: define a macro to extract the number of l2 caches from 2978c2ecf20Sopenharmony_ci * mem_features. 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_ci nl2c = ((pfdev->features.mem_features >> 8) & GENMASK(3, 0)) + 1; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci /* 3028c2ecf20Sopenharmony_ci * shader_present might be sparse, but the counters layout 3038c2ecf20Sopenharmony_ci * forces to dump unused regions too, hence the fls64() call 3048c2ecf20Sopenharmony_ci * instead of hweight64(). 3058c2ecf20Sopenharmony_ci */ 3068c2ecf20Sopenharmony_ci ncores = fls64(pfdev->features.shader_present); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci /* 3098c2ecf20Sopenharmony_ci * There's always one JM and one Tiler block, hence the '+ 2' 3108c2ecf20Sopenharmony_ci * here. 3118c2ecf20Sopenharmony_ci */ 3128c2ecf20Sopenharmony_ci size = (nl2c + ncores + 2) * 3138c2ecf20Sopenharmony_ci COUNTERS_PER_BLOCK * BYTES_PER_COUNTER; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci perfcnt = devm_kzalloc(pfdev->dev, sizeof(*perfcnt), GFP_KERNEL); 3178c2ecf20Sopenharmony_ci if (!perfcnt) 3188c2ecf20Sopenharmony_ci return -ENOMEM; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci perfcnt->bosize = size; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* Start with everything disabled. */ 3238c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PERFCNT_CFG, 3248c2ecf20Sopenharmony_ci GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_OFF)); 3258c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_JM_EN, 0); 3268c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_SHADER_EN, 0); 3278c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_MMU_L2_EN, 0); 3288c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_TILER_EN, 0); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci init_completion(&perfcnt->dump_comp); 3318c2ecf20Sopenharmony_ci mutex_init(&perfcnt->lock); 3328c2ecf20Sopenharmony_ci pfdev->perfcnt = perfcnt; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci return 0; 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_civoid panfrost_perfcnt_fini(struct panfrost_device *pfdev) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci /* Disable everything before leaving. */ 3408c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PERFCNT_CFG, 3418c2ecf20Sopenharmony_ci GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_OFF)); 3428c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_JM_EN, 0); 3438c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_SHADER_EN, 0); 3448c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_MMU_L2_EN, 0); 3458c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PRFCNT_TILER_EN, 0); 3468c2ecf20Sopenharmony_ci} 347