162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* Copyright (C) 2014-2018 Broadcom */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/circ_buf.h> 562306a36Sopenharmony_ci#include <linux/ctype.h> 662306a36Sopenharmony_ci#include <linux/debugfs.h> 762306a36Sopenharmony_ci#include <linux/seq_file.h> 862306a36Sopenharmony_ci#include <linux/string_helpers.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <drm/drm_debugfs.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "v3d_drv.h" 1362306a36Sopenharmony_ci#include "v3d_regs.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define REGDEF(reg) { reg, #reg } 1662306a36Sopenharmony_cistruct v3d_reg_def { 1762306a36Sopenharmony_ci u32 reg; 1862306a36Sopenharmony_ci const char *name; 1962306a36Sopenharmony_ci}; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic const struct v3d_reg_def v3d_hub_reg_defs[] = { 2262306a36Sopenharmony_ci REGDEF(V3D_HUB_AXICFG), 2362306a36Sopenharmony_ci REGDEF(V3D_HUB_UIFCFG), 2462306a36Sopenharmony_ci REGDEF(V3D_HUB_IDENT0), 2562306a36Sopenharmony_ci REGDEF(V3D_HUB_IDENT1), 2662306a36Sopenharmony_ci REGDEF(V3D_HUB_IDENT2), 2762306a36Sopenharmony_ci REGDEF(V3D_HUB_IDENT3), 2862306a36Sopenharmony_ci REGDEF(V3D_HUB_INT_STS), 2962306a36Sopenharmony_ci REGDEF(V3D_HUB_INT_MSK_STS), 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci REGDEF(V3D_MMU_CTL), 3262306a36Sopenharmony_ci REGDEF(V3D_MMU_VIO_ADDR), 3362306a36Sopenharmony_ci REGDEF(V3D_MMU_VIO_ID), 3462306a36Sopenharmony_ci REGDEF(V3D_MMU_DEBUG_INFO), 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic const struct v3d_reg_def v3d_gca_reg_defs[] = { 3862306a36Sopenharmony_ci REGDEF(V3D_GCA_SAFE_SHUTDOWN), 3962306a36Sopenharmony_ci REGDEF(V3D_GCA_SAFE_SHUTDOWN_ACK), 4062306a36Sopenharmony_ci}; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic const struct v3d_reg_def v3d_core_reg_defs[] = { 4362306a36Sopenharmony_ci REGDEF(V3D_CTL_IDENT0), 4462306a36Sopenharmony_ci REGDEF(V3D_CTL_IDENT1), 4562306a36Sopenharmony_ci REGDEF(V3D_CTL_IDENT2), 4662306a36Sopenharmony_ci REGDEF(V3D_CTL_MISCCFG), 4762306a36Sopenharmony_ci REGDEF(V3D_CTL_INT_STS), 4862306a36Sopenharmony_ci REGDEF(V3D_CTL_INT_MSK_STS), 4962306a36Sopenharmony_ci REGDEF(V3D_CLE_CT0CS), 5062306a36Sopenharmony_ci REGDEF(V3D_CLE_CT0CA), 5162306a36Sopenharmony_ci REGDEF(V3D_CLE_CT0EA), 5262306a36Sopenharmony_ci REGDEF(V3D_CLE_CT1CS), 5362306a36Sopenharmony_ci REGDEF(V3D_CLE_CT1CA), 5462306a36Sopenharmony_ci REGDEF(V3D_CLE_CT1EA), 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci REGDEF(V3D_PTB_BPCA), 5762306a36Sopenharmony_ci REGDEF(V3D_PTB_BPCS), 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci REGDEF(V3D_GMP_STATUS), 6062306a36Sopenharmony_ci REGDEF(V3D_GMP_CFG), 6162306a36Sopenharmony_ci REGDEF(V3D_GMP_VIO_ADDR), 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci REGDEF(V3D_ERR_FDBGO), 6462306a36Sopenharmony_ci REGDEF(V3D_ERR_FDBGB), 6562306a36Sopenharmony_ci REGDEF(V3D_ERR_FDBGS), 6662306a36Sopenharmony_ci REGDEF(V3D_ERR_STAT), 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic const struct v3d_reg_def v3d_csd_reg_defs[] = { 7062306a36Sopenharmony_ci REGDEF(V3D_CSD_STATUS), 7162306a36Sopenharmony_ci REGDEF(V3D_CSD_CURRENT_CFG0), 7262306a36Sopenharmony_ci REGDEF(V3D_CSD_CURRENT_CFG1), 7362306a36Sopenharmony_ci REGDEF(V3D_CSD_CURRENT_CFG2), 7462306a36Sopenharmony_ci REGDEF(V3D_CSD_CURRENT_CFG3), 7562306a36Sopenharmony_ci REGDEF(V3D_CSD_CURRENT_CFG4), 7662306a36Sopenharmony_ci REGDEF(V3D_CSD_CURRENT_CFG5), 7762306a36Sopenharmony_ci REGDEF(V3D_CSD_CURRENT_CFG6), 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci struct drm_debugfs_entry *entry = m->private; 8362306a36Sopenharmony_ci struct drm_device *dev = entry->dev; 8462306a36Sopenharmony_ci struct v3d_dev *v3d = to_v3d_dev(dev); 8562306a36Sopenharmony_ci int i, core; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(v3d_hub_reg_defs); i++) { 8862306a36Sopenharmony_ci seq_printf(m, "%s (0x%04x): 0x%08x\n", 8962306a36Sopenharmony_ci v3d_hub_reg_defs[i].name, v3d_hub_reg_defs[i].reg, 9062306a36Sopenharmony_ci V3D_READ(v3d_hub_reg_defs[i].reg)); 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (v3d->ver < 41) { 9462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(v3d_gca_reg_defs); i++) { 9562306a36Sopenharmony_ci seq_printf(m, "%s (0x%04x): 0x%08x\n", 9662306a36Sopenharmony_ci v3d_gca_reg_defs[i].name, 9762306a36Sopenharmony_ci v3d_gca_reg_defs[i].reg, 9862306a36Sopenharmony_ci V3D_GCA_READ(v3d_gca_reg_defs[i].reg)); 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci for (core = 0; core < v3d->cores; core++) { 10362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(v3d_core_reg_defs); i++) { 10462306a36Sopenharmony_ci seq_printf(m, "core %d %s (0x%04x): 0x%08x\n", 10562306a36Sopenharmony_ci core, 10662306a36Sopenharmony_ci v3d_core_reg_defs[i].name, 10762306a36Sopenharmony_ci v3d_core_reg_defs[i].reg, 10862306a36Sopenharmony_ci V3D_CORE_READ(core, 10962306a36Sopenharmony_ci v3d_core_reg_defs[i].reg)); 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if (v3d_has_csd(v3d)) { 11362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) { 11462306a36Sopenharmony_ci seq_printf(m, "core %d %s (0x%04x): 0x%08x\n", 11562306a36Sopenharmony_ci core, 11662306a36Sopenharmony_ci v3d_csd_reg_defs[i].name, 11762306a36Sopenharmony_ci v3d_csd_reg_defs[i].reg, 11862306a36Sopenharmony_ci V3D_CORE_READ(core, 11962306a36Sopenharmony_ci v3d_csd_reg_defs[i].reg)); 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci return 0; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic int v3d_v3d_debugfs_ident(struct seq_file *m, void *unused) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci struct drm_debugfs_entry *entry = m->private; 13062306a36Sopenharmony_ci struct drm_device *dev = entry->dev; 13162306a36Sopenharmony_ci struct v3d_dev *v3d = to_v3d_dev(dev); 13262306a36Sopenharmony_ci u32 ident0, ident1, ident2, ident3, cores; 13362306a36Sopenharmony_ci int core; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci ident0 = V3D_READ(V3D_HUB_IDENT0); 13662306a36Sopenharmony_ci ident1 = V3D_READ(V3D_HUB_IDENT1); 13762306a36Sopenharmony_ci ident2 = V3D_READ(V3D_HUB_IDENT2); 13862306a36Sopenharmony_ci ident3 = V3D_READ(V3D_HUB_IDENT3); 13962306a36Sopenharmony_ci cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci seq_printf(m, "Revision: %d.%d.%d.%d\n", 14262306a36Sopenharmony_ci V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER), 14362306a36Sopenharmony_ci V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_REV), 14462306a36Sopenharmony_ci V3D_GET_FIELD(ident3, V3D_HUB_IDENT3_IPREV), 14562306a36Sopenharmony_ci V3D_GET_FIELD(ident3, V3D_HUB_IDENT3_IPIDX)); 14662306a36Sopenharmony_ci seq_printf(m, "MMU: %s\n", 14762306a36Sopenharmony_ci str_yes_no(ident2 & V3D_HUB_IDENT2_WITH_MMU)); 14862306a36Sopenharmony_ci seq_printf(m, "TFU: %s\n", 14962306a36Sopenharmony_ci str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TFU)); 15062306a36Sopenharmony_ci seq_printf(m, "TSY: %s\n", 15162306a36Sopenharmony_ci str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TSY)); 15262306a36Sopenharmony_ci seq_printf(m, "MSO: %s\n", 15362306a36Sopenharmony_ci str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_MSO)); 15462306a36Sopenharmony_ci seq_printf(m, "L3C: %s (%dkb)\n", 15562306a36Sopenharmony_ci str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_L3C), 15662306a36Sopenharmony_ci V3D_GET_FIELD(ident2, V3D_HUB_IDENT2_L3C_NKB)); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci for (core = 0; core < cores; core++) { 15962306a36Sopenharmony_ci u32 misccfg; 16062306a36Sopenharmony_ci u32 nslc, ntmu, qups; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci ident0 = V3D_CORE_READ(core, V3D_CTL_IDENT0); 16362306a36Sopenharmony_ci ident1 = V3D_CORE_READ(core, V3D_CTL_IDENT1); 16462306a36Sopenharmony_ci ident2 = V3D_CORE_READ(core, V3D_CTL_IDENT2); 16562306a36Sopenharmony_ci misccfg = V3D_CORE_READ(core, V3D_CTL_MISCCFG); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci nslc = V3D_GET_FIELD(ident1, V3D_IDENT1_NSLC); 16862306a36Sopenharmony_ci ntmu = V3D_GET_FIELD(ident1, V3D_IDENT1_NTMU); 16962306a36Sopenharmony_ci qups = V3D_GET_FIELD(ident1, V3D_IDENT1_QUPS); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci seq_printf(m, "Core %d:\n", core); 17262306a36Sopenharmony_ci seq_printf(m, " Revision: %d.%d\n", 17362306a36Sopenharmony_ci V3D_GET_FIELD(ident0, V3D_IDENT0_VER), 17462306a36Sopenharmony_ci V3D_GET_FIELD(ident1, V3D_IDENT1_REV)); 17562306a36Sopenharmony_ci seq_printf(m, " Slices: %d\n", nslc); 17662306a36Sopenharmony_ci seq_printf(m, " TMUs: %d\n", nslc * ntmu); 17762306a36Sopenharmony_ci seq_printf(m, " QPUs: %d\n", nslc * qups); 17862306a36Sopenharmony_ci seq_printf(m, " Semaphores: %d\n", 17962306a36Sopenharmony_ci V3D_GET_FIELD(ident1, V3D_IDENT1_NSEM)); 18062306a36Sopenharmony_ci seq_printf(m, " BCG int: %d\n", 18162306a36Sopenharmony_ci (ident2 & V3D_IDENT2_BCG_INT) != 0); 18262306a36Sopenharmony_ci seq_printf(m, " Override TMU: %d\n", 18362306a36Sopenharmony_ci (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0); 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci return 0; 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic int v3d_debugfs_bo_stats(struct seq_file *m, void *unused) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci struct drm_debugfs_entry *entry = m->private; 19262306a36Sopenharmony_ci struct drm_device *dev = entry->dev; 19362306a36Sopenharmony_ci struct v3d_dev *v3d = to_v3d_dev(dev); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci mutex_lock(&v3d->bo_lock); 19662306a36Sopenharmony_ci seq_printf(m, "allocated bos: %d\n", 19762306a36Sopenharmony_ci v3d->bo_stats.num_allocated); 19862306a36Sopenharmony_ci seq_printf(m, "allocated bo size (kb): %ld\n", 19962306a36Sopenharmony_ci (long)v3d->bo_stats.pages_allocated << (PAGE_SHIFT - 10)); 20062306a36Sopenharmony_ci mutex_unlock(&v3d->bo_lock); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci return 0; 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic int v3d_measure_clock(struct seq_file *m, void *unused) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci struct drm_debugfs_entry *entry = m->private; 20862306a36Sopenharmony_ci struct drm_device *dev = entry->dev; 20962306a36Sopenharmony_ci struct v3d_dev *v3d = to_v3d_dev(dev); 21062306a36Sopenharmony_ci uint32_t cycles; 21162306a36Sopenharmony_ci int core = 0; 21262306a36Sopenharmony_ci int measure_ms = 1000; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (v3d->ver >= 40) { 21562306a36Sopenharmony_ci V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3, 21662306a36Sopenharmony_ci V3D_SET_FIELD(V3D_PCTR_CYCLE_COUNT, 21762306a36Sopenharmony_ci V3D_PCTR_S0)); 21862306a36Sopenharmony_ci V3D_CORE_WRITE(core, V3D_V4_PCTR_0_CLR, 1); 21962306a36Sopenharmony_ci V3D_CORE_WRITE(core, V3D_V4_PCTR_0_EN, 1); 22062306a36Sopenharmony_ci } else { 22162306a36Sopenharmony_ci V3D_CORE_WRITE(core, V3D_V3_PCTR_0_PCTRS0, 22262306a36Sopenharmony_ci V3D_PCTR_CYCLE_COUNT); 22362306a36Sopenharmony_ci V3D_CORE_WRITE(core, V3D_V3_PCTR_0_CLR, 1); 22462306a36Sopenharmony_ci V3D_CORE_WRITE(core, V3D_V3_PCTR_0_EN, 22562306a36Sopenharmony_ci V3D_V3_PCTR_0_EN_ENABLE | 22662306a36Sopenharmony_ci 1); 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci msleep(measure_ms); 22962306a36Sopenharmony_ci cycles = V3D_CORE_READ(core, V3D_PCTR_0_PCTR0); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci seq_printf(m, "cycles: %d (%d.%d Mhz)\n", 23262306a36Sopenharmony_ci cycles, 23362306a36Sopenharmony_ci cycles / (measure_ms * 1000), 23462306a36Sopenharmony_ci (cycles / (measure_ms * 100)) % 10); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci return 0; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic const struct drm_debugfs_info v3d_debugfs_list[] = { 24062306a36Sopenharmony_ci {"v3d_ident", v3d_v3d_debugfs_ident, 0}, 24162306a36Sopenharmony_ci {"v3d_regs", v3d_v3d_debugfs_regs, 0}, 24262306a36Sopenharmony_ci {"measure_clock", v3d_measure_clock, 0}, 24362306a36Sopenharmony_ci {"bo_stats", v3d_debugfs_bo_stats, 0}, 24462306a36Sopenharmony_ci}; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_civoid 24762306a36Sopenharmony_civ3d_debugfs_init(struct drm_minor *minor) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci drm_debugfs_add_files(minor->dev, v3d_debugfs_list, ARRAY_SIZE(v3d_debugfs_list)); 25062306a36Sopenharmony_ci} 251