18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright 2018 Marty E. Plummer <hanetzer@startmail.com> */ 38c2ecf20Sopenharmony_ci/* Copyright 2019 Linaro, Ltd., Rob Herring <robh@kernel.org> */ 48c2ecf20Sopenharmony_ci/* Copyright 2019 Collabora ltd. */ 58c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 68c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 78c2ecf20Sopenharmony_ci#include <linux/delay.h> 88c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 98c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 108c2ecf20Sopenharmony_ci#include <linux/io.h> 118c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 128c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 138c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "panfrost_device.h" 168c2ecf20Sopenharmony_ci#include "panfrost_features.h" 178c2ecf20Sopenharmony_ci#include "panfrost_issues.h" 188c2ecf20Sopenharmony_ci#include "panfrost_gpu.h" 198c2ecf20Sopenharmony_ci#include "panfrost_perfcnt.h" 208c2ecf20Sopenharmony_ci#include "panfrost_regs.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic irqreturn_t panfrost_gpu_irq_handler(int irq, void *data) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci struct panfrost_device *pfdev = data; 258c2ecf20Sopenharmony_ci u32 state = gpu_read(pfdev, GPU_INT_STAT); 268c2ecf20Sopenharmony_ci u32 fault_status = gpu_read(pfdev, GPU_FAULT_STATUS); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci if (!state) 298c2ecf20Sopenharmony_ci return IRQ_NONE; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci if (state & GPU_IRQ_MASK_ERROR) { 328c2ecf20Sopenharmony_ci u64 address = (u64) gpu_read(pfdev, GPU_FAULT_ADDRESS_HI) << 32; 338c2ecf20Sopenharmony_ci address |= gpu_read(pfdev, GPU_FAULT_ADDRESS_LO); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci dev_warn(pfdev->dev, "GPU Fault 0x%08x (%s) at 0x%016llx\n", 368c2ecf20Sopenharmony_ci fault_status & 0xFF, panfrost_exception_name(pfdev, fault_status), 378c2ecf20Sopenharmony_ci address); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci if (state & GPU_IRQ_MULTIPLE_FAULT) 408c2ecf20Sopenharmony_ci dev_warn(pfdev->dev, "There were multiple GPU faults - some have not been reported\n"); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_INT_MASK, 0); 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci if (state & GPU_IRQ_PERFCNT_SAMPLE_COMPLETED) 468c2ecf20Sopenharmony_ci panfrost_perfcnt_sample_done(pfdev); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci if (state & GPU_IRQ_CLEAN_CACHES_COMPLETED) 498c2ecf20Sopenharmony_ci panfrost_perfcnt_clean_cache_done(pfdev); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_INT_CLEAR, state); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci return IRQ_HANDLED; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciint panfrost_gpu_soft_reset(struct panfrost_device *pfdev) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci int ret; 598c2ecf20Sopenharmony_ci u32 val; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_INT_MASK, 0); 628c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_RESET_COMPLETED); 638c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_CMD, GPU_CMD_SOFT_RESET); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci ret = readl_relaxed_poll_timeout(pfdev->iomem + GPU_INT_RAWSTAT, 668c2ecf20Sopenharmony_ci val, val & GPU_IRQ_RESET_COMPLETED, 100, 10000); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (ret) { 698c2ecf20Sopenharmony_ci dev_err(pfdev->dev, "gpu soft reset timed out\n"); 708c2ecf20Sopenharmony_ci return ret; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_MASK_ALL); 748c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_INT_MASK, GPU_IRQ_MASK_ALL); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci return 0; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_civoid panfrost_gpu_amlogic_quirk(struct panfrost_device *pfdev) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci /* 828c2ecf20Sopenharmony_ci * The Amlogic integrated Mali-T820, Mali-G31 & Mali-G52 needs 838c2ecf20Sopenharmony_ci * these undocumented bits in GPU_PWR_OVERRIDE1 to be set in order 848c2ecf20Sopenharmony_ci * to operate correctly. 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PWR_KEY, GPU_PWR_KEY_UNLOCK); 878c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_PWR_OVERRIDE1, 0xfff | (0x20 << 16)); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic void panfrost_gpu_init_quirks(struct panfrost_device *pfdev) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci u32 quirks = 0; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (panfrost_has_hw_issue(pfdev, HW_ISSUE_8443) || 958c2ecf20Sopenharmony_ci panfrost_has_hw_issue(pfdev, HW_ISSUE_11035)) 968c2ecf20Sopenharmony_ci quirks |= SC_LS_PAUSEBUFFER_DISABLE; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (panfrost_has_hw_issue(pfdev, HW_ISSUE_10327)) 998c2ecf20Sopenharmony_ci quirks |= SC_SDC_DISABLE_OQ_DISCARD; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if (panfrost_has_hw_issue(pfdev, HW_ISSUE_10797)) 1028c2ecf20Sopenharmony_ci quirks |= SC_ENABLE_TEXGRD_FLAGS; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (!panfrost_has_hw_issue(pfdev, GPUCORE_1619)) { 1058c2ecf20Sopenharmony_ci if (panfrost_model_cmp(pfdev, 0x750) < 0) /* T60x, T62x, T72x */ 1068c2ecf20Sopenharmony_ci quirks |= SC_LS_ATTR_CHECK_DISABLE; 1078c2ecf20Sopenharmony_ci else if (panfrost_model_cmp(pfdev, 0x880) <= 0) /* T76x, T8xx */ 1088c2ecf20Sopenharmony_ci quirks |= SC_LS_ALLOW_ATTR_TYPES; 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci if (panfrost_has_hw_feature(pfdev, HW_FEATURE_TLS_HASHING)) 1128c2ecf20Sopenharmony_ci quirks |= SC_TLS_HASH_ENABLE; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (quirks) 1158c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_SHADER_CONFIG, quirks); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci quirks = gpu_read(pfdev, GPU_TILER_CONFIG); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* Set tiler clock gate override if required */ 1218c2ecf20Sopenharmony_ci if (panfrost_has_hw_issue(pfdev, HW_ISSUE_T76X_3953)) 1228c2ecf20Sopenharmony_ci quirks |= TC_CLOCK_GATE_OVERRIDE; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_TILER_CONFIG, quirks); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci quirks = gpu_read(pfdev, GPU_L2_MMU_CONFIG); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* Limit read & write ID width for AXI */ 1308c2ecf20Sopenharmony_ci if (panfrost_has_hw_feature(pfdev, HW_FEATURE_3BIT_EXT_RW_L2_MMU_CONFIG)) 1318c2ecf20Sopenharmony_ci quirks &= ~(L2_MMU_CONFIG_3BIT_LIMIT_EXTERNAL_READS | 1328c2ecf20Sopenharmony_ci L2_MMU_CONFIG_3BIT_LIMIT_EXTERNAL_WRITES); 1338c2ecf20Sopenharmony_ci else 1348c2ecf20Sopenharmony_ci quirks &= ~(L2_MMU_CONFIG_LIMIT_EXTERNAL_READS | 1358c2ecf20Sopenharmony_ci L2_MMU_CONFIG_LIMIT_EXTERNAL_WRITES); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_L2_MMU_CONFIG, quirks); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci quirks = 0; 1408c2ecf20Sopenharmony_ci if ((panfrost_model_eq(pfdev, 0x860) || panfrost_model_eq(pfdev, 0x880)) && 1418c2ecf20Sopenharmony_ci pfdev->features.revision >= 0x2000) 1428c2ecf20Sopenharmony_ci quirks |= JM_MAX_JOB_THROTTLE_LIMIT << JM_JOB_THROTTLE_LIMIT_SHIFT; 1438c2ecf20Sopenharmony_ci else if (panfrost_model_eq(pfdev, 0x6000) && 1448c2ecf20Sopenharmony_ci pfdev->features.coherency_features == COHERENCY_ACE) 1458c2ecf20Sopenharmony_ci quirks |= (COHERENCY_ACE_LITE | COHERENCY_ACE) << 1468c2ecf20Sopenharmony_ci JM_FORCE_COHERENCY_FEATURES_SHIFT; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (quirks) 1498c2ecf20Sopenharmony_ci gpu_write(pfdev, GPU_JM_CONFIG, quirks); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* Here goes platform specific quirks */ 1528c2ecf20Sopenharmony_ci if (pfdev->comp->vendor_quirk) 1538c2ecf20Sopenharmony_ci pfdev->comp->vendor_quirk(pfdev); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#define MAX_HW_REVS 6 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistruct panfrost_model { 1598c2ecf20Sopenharmony_ci const char *name; 1608c2ecf20Sopenharmony_ci u32 id; 1618c2ecf20Sopenharmony_ci u32 id_mask; 1628c2ecf20Sopenharmony_ci u64 features; 1638c2ecf20Sopenharmony_ci u64 issues; 1648c2ecf20Sopenharmony_ci struct { 1658c2ecf20Sopenharmony_ci u32 revision; 1668c2ecf20Sopenharmony_ci u64 issues; 1678c2ecf20Sopenharmony_ci } revs[MAX_HW_REVS]; 1688c2ecf20Sopenharmony_ci}; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci#define GPU_MODEL(_name, _id, ...) \ 1718c2ecf20Sopenharmony_ci{\ 1728c2ecf20Sopenharmony_ci .name = __stringify(_name), \ 1738c2ecf20Sopenharmony_ci .id = _id, \ 1748c2ecf20Sopenharmony_ci .features = hw_features_##_name, \ 1758c2ecf20Sopenharmony_ci .issues = hw_issues_##_name, \ 1768c2ecf20Sopenharmony_ci .revs = { __VA_ARGS__ }, \ 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci#define GPU_REV_EXT(name, _rev, _p, _s, stat) \ 1808c2ecf20Sopenharmony_ci{\ 1818c2ecf20Sopenharmony_ci .revision = (_rev) << 12 | (_p) << 4 | (_s), \ 1828c2ecf20Sopenharmony_ci .issues = hw_issues_##name##_r##_rev##p##_p##stat, \ 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci#define GPU_REV(name, r, p) GPU_REV_EXT(name, r, p, 0, ) 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic const struct panfrost_model gpu_models[] = { 1878c2ecf20Sopenharmony_ci /* T60x has an oddball version */ 1888c2ecf20Sopenharmony_ci GPU_MODEL(t600, 0x600, 1898c2ecf20Sopenharmony_ci GPU_REV_EXT(t600, 0, 0, 1, _15dev0)), 1908c2ecf20Sopenharmony_ci GPU_MODEL(t620, 0x620, 1918c2ecf20Sopenharmony_ci GPU_REV(t620, 0, 1), GPU_REV(t620, 1, 0)), 1928c2ecf20Sopenharmony_ci GPU_MODEL(t720, 0x720), 1938c2ecf20Sopenharmony_ci GPU_MODEL(t760, 0x750, 1948c2ecf20Sopenharmony_ci GPU_REV(t760, 0, 0), GPU_REV(t760, 0, 1), 1958c2ecf20Sopenharmony_ci GPU_REV_EXT(t760, 0, 1, 0, _50rel0), 1968c2ecf20Sopenharmony_ci GPU_REV(t760, 0, 2), GPU_REV(t760, 0, 3)), 1978c2ecf20Sopenharmony_ci GPU_MODEL(t820, 0x820), 1988c2ecf20Sopenharmony_ci GPU_MODEL(t830, 0x830), 1998c2ecf20Sopenharmony_ci GPU_MODEL(t860, 0x860), 2008c2ecf20Sopenharmony_ci GPU_MODEL(t880, 0x880), 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci GPU_MODEL(g71, 0x6000, 2038c2ecf20Sopenharmony_ci GPU_REV_EXT(g71, 0, 0, 1, _05dev0)), 2048c2ecf20Sopenharmony_ci GPU_MODEL(g72, 0x6001), 2058c2ecf20Sopenharmony_ci GPU_MODEL(g51, 0x7000), 2068c2ecf20Sopenharmony_ci GPU_MODEL(g76, 0x7001), 2078c2ecf20Sopenharmony_ci GPU_MODEL(g52, 0x7002), 2088c2ecf20Sopenharmony_ci GPU_MODEL(g31, 0x7003, 2098c2ecf20Sopenharmony_ci GPU_REV(g31, 1, 0)), 2108c2ecf20Sopenharmony_ci}; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic void panfrost_gpu_init_features(struct panfrost_device *pfdev) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci u32 gpu_id, num_js, major, minor, status, rev; 2158c2ecf20Sopenharmony_ci const char *name = "unknown"; 2168c2ecf20Sopenharmony_ci u64 hw_feat = 0; 2178c2ecf20Sopenharmony_ci u64 hw_issues = hw_issues_all; 2188c2ecf20Sopenharmony_ci const struct panfrost_model *model; 2198c2ecf20Sopenharmony_ci int i; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci pfdev->features.l2_features = gpu_read(pfdev, GPU_L2_FEATURES); 2228c2ecf20Sopenharmony_ci pfdev->features.core_features = gpu_read(pfdev, GPU_CORE_FEATURES); 2238c2ecf20Sopenharmony_ci pfdev->features.tiler_features = gpu_read(pfdev, GPU_TILER_FEATURES); 2248c2ecf20Sopenharmony_ci pfdev->features.mem_features = gpu_read(pfdev, GPU_MEM_FEATURES); 2258c2ecf20Sopenharmony_ci pfdev->features.mmu_features = gpu_read(pfdev, GPU_MMU_FEATURES); 2268c2ecf20Sopenharmony_ci pfdev->features.thread_features = gpu_read(pfdev, GPU_THREAD_FEATURES); 2278c2ecf20Sopenharmony_ci pfdev->features.max_threads = gpu_read(pfdev, GPU_THREAD_MAX_THREADS); 2288c2ecf20Sopenharmony_ci pfdev->features.thread_max_workgroup_sz = gpu_read(pfdev, GPU_THREAD_MAX_WORKGROUP_SIZE); 2298c2ecf20Sopenharmony_ci pfdev->features.thread_max_barrier_sz = gpu_read(pfdev, GPU_THREAD_MAX_BARRIER_SIZE); 2308c2ecf20Sopenharmony_ci pfdev->features.coherency_features = gpu_read(pfdev, GPU_COHERENCY_FEATURES); 2318c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 2328c2ecf20Sopenharmony_ci pfdev->features.texture_features[i] = gpu_read(pfdev, GPU_TEXTURE_FEATURES(i)); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci pfdev->features.as_present = gpu_read(pfdev, GPU_AS_PRESENT); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci pfdev->features.js_present = gpu_read(pfdev, GPU_JS_PRESENT); 2378c2ecf20Sopenharmony_ci num_js = hweight32(pfdev->features.js_present); 2388c2ecf20Sopenharmony_ci for (i = 0; i < num_js; i++) 2398c2ecf20Sopenharmony_ci pfdev->features.js_features[i] = gpu_read(pfdev, GPU_JS_FEATURES(i)); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci pfdev->features.shader_present = gpu_read(pfdev, GPU_SHADER_PRESENT_LO); 2428c2ecf20Sopenharmony_ci pfdev->features.shader_present |= (u64)gpu_read(pfdev, GPU_SHADER_PRESENT_HI) << 32; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci pfdev->features.tiler_present = gpu_read(pfdev, GPU_TILER_PRESENT_LO); 2458c2ecf20Sopenharmony_ci pfdev->features.tiler_present |= (u64)gpu_read(pfdev, GPU_TILER_PRESENT_HI) << 32; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci pfdev->features.l2_present = gpu_read(pfdev, GPU_L2_PRESENT_LO); 2488c2ecf20Sopenharmony_ci pfdev->features.l2_present |= (u64)gpu_read(pfdev, GPU_L2_PRESENT_HI) << 32; 2498c2ecf20Sopenharmony_ci pfdev->features.nr_core_groups = hweight64(pfdev->features.l2_present); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci pfdev->features.stack_present = gpu_read(pfdev, GPU_STACK_PRESENT_LO); 2528c2ecf20Sopenharmony_ci pfdev->features.stack_present |= (u64)gpu_read(pfdev, GPU_STACK_PRESENT_HI) << 32; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci pfdev->features.thread_tls_alloc = gpu_read(pfdev, GPU_THREAD_TLS_ALLOC); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci gpu_id = gpu_read(pfdev, GPU_ID); 2578c2ecf20Sopenharmony_ci pfdev->features.revision = gpu_id & 0xffff; 2588c2ecf20Sopenharmony_ci pfdev->features.id = gpu_id >> 16; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci /* The T60x has an oddball ID value. Fix it up to the standard Midgard 2618c2ecf20Sopenharmony_ci * format so we (and userspace) don't have to special case it. 2628c2ecf20Sopenharmony_ci */ 2638c2ecf20Sopenharmony_ci if (pfdev->features.id == 0x6956) 2648c2ecf20Sopenharmony_ci pfdev->features.id = 0x0600; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci major = (pfdev->features.revision >> 12) & 0xf; 2678c2ecf20Sopenharmony_ci minor = (pfdev->features.revision >> 4) & 0xff; 2688c2ecf20Sopenharmony_ci status = pfdev->features.revision & 0xf; 2698c2ecf20Sopenharmony_ci rev = pfdev->features.revision; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci gpu_id = pfdev->features.id; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci for (model = gpu_models; model->name; model++) { 2748c2ecf20Sopenharmony_ci int best = -1; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci if (!panfrost_model_eq(pfdev, model->id)) 2778c2ecf20Sopenharmony_ci continue; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci name = model->name; 2808c2ecf20Sopenharmony_ci hw_feat = model->features; 2818c2ecf20Sopenharmony_ci hw_issues |= model->issues; 2828c2ecf20Sopenharmony_ci for (i = 0; i < MAX_HW_REVS; i++) { 2838c2ecf20Sopenharmony_ci if (model->revs[i].revision == rev) { 2848c2ecf20Sopenharmony_ci best = i; 2858c2ecf20Sopenharmony_ci break; 2868c2ecf20Sopenharmony_ci } else if (model->revs[i].revision == (rev & ~0xf)) 2878c2ecf20Sopenharmony_ci best = i; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (best >= 0) 2918c2ecf20Sopenharmony_ci hw_issues |= model->revs[best].issues; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci break; 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci bitmap_from_u64(pfdev->features.hw_features, hw_feat); 2978c2ecf20Sopenharmony_ci bitmap_from_u64(pfdev->features.hw_issues, hw_issues); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci dev_info(pfdev->dev, "mali-%s id 0x%x major 0x%x minor 0x%x status 0x%x", 3008c2ecf20Sopenharmony_ci name, gpu_id, major, minor, status); 3018c2ecf20Sopenharmony_ci dev_info(pfdev->dev, "features: %64pb, issues: %64pb", 3028c2ecf20Sopenharmony_ci pfdev->features.hw_features, 3038c2ecf20Sopenharmony_ci pfdev->features.hw_issues); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci dev_info(pfdev->dev, "Features: L2:0x%08x Shader:0x%08x Tiler:0x%08x Mem:0x%0x MMU:0x%08x AS:0x%x JS:0x%x", 3068c2ecf20Sopenharmony_ci pfdev->features.l2_features, 3078c2ecf20Sopenharmony_ci pfdev->features.core_features, 3088c2ecf20Sopenharmony_ci pfdev->features.tiler_features, 3098c2ecf20Sopenharmony_ci pfdev->features.mem_features, 3108c2ecf20Sopenharmony_ci pfdev->features.mmu_features, 3118c2ecf20Sopenharmony_ci pfdev->features.as_present, 3128c2ecf20Sopenharmony_ci pfdev->features.js_present); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci dev_info(pfdev->dev, "shader_present=0x%0llx l2_present=0x%0llx", 3158c2ecf20Sopenharmony_ci pfdev->features.shader_present, pfdev->features.l2_present); 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_civoid panfrost_gpu_power_on(struct panfrost_device *pfdev) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci int ret; 3218c2ecf20Sopenharmony_ci u32 val; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci panfrost_gpu_init_quirks(pfdev); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* Just turn on everything for now */ 3268c2ecf20Sopenharmony_ci gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present); 3278c2ecf20Sopenharmony_ci ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO, 3288c2ecf20Sopenharmony_ci val, val == pfdev->features.l2_present, 100, 20000); 3298c2ecf20Sopenharmony_ci if (ret) 3308c2ecf20Sopenharmony_ci dev_err(pfdev->dev, "error powering up gpu L2"); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci gpu_write(pfdev, SHADER_PWRON_LO, pfdev->features.shader_present); 3338c2ecf20Sopenharmony_ci ret = readl_relaxed_poll_timeout(pfdev->iomem + SHADER_READY_LO, 3348c2ecf20Sopenharmony_ci val, val == pfdev->features.shader_present, 100, 20000); 3358c2ecf20Sopenharmony_ci if (ret) 3368c2ecf20Sopenharmony_ci dev_err(pfdev->dev, "error powering up gpu shader"); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci gpu_write(pfdev, TILER_PWRON_LO, pfdev->features.tiler_present); 3398c2ecf20Sopenharmony_ci ret = readl_relaxed_poll_timeout(pfdev->iomem + TILER_READY_LO, 3408c2ecf20Sopenharmony_ci val, val == pfdev->features.tiler_present, 100, 1000); 3418c2ecf20Sopenharmony_ci if (ret) 3428c2ecf20Sopenharmony_ci dev_err(pfdev->dev, "error powering up gpu tiler"); 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_civoid panfrost_gpu_power_off(struct panfrost_device *pfdev) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci gpu_write(pfdev, TILER_PWROFF_LO, 0); 3488c2ecf20Sopenharmony_ci gpu_write(pfdev, SHADER_PWROFF_LO, 0); 3498c2ecf20Sopenharmony_ci gpu_write(pfdev, L2_PWROFF_LO, 0); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ciint panfrost_gpu_init(struct panfrost_device *pfdev) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci int err, irq; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci err = panfrost_gpu_soft_reset(pfdev); 3578c2ecf20Sopenharmony_ci if (err) 3588c2ecf20Sopenharmony_ci return err; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci panfrost_gpu_init_features(pfdev); 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci err = dma_set_mask_and_coherent(pfdev->dev, 3638c2ecf20Sopenharmony_ci DMA_BIT_MASK(FIELD_GET(0xff00, pfdev->features.mmu_features))); 3648c2ecf20Sopenharmony_ci if (err) 3658c2ecf20Sopenharmony_ci return err; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci dma_set_max_seg_size(pfdev->dev, UINT_MAX); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "gpu"); 3708c2ecf20Sopenharmony_ci if (irq <= 0) 3718c2ecf20Sopenharmony_ci return -ENODEV; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci err = devm_request_irq(pfdev->dev, irq, panfrost_gpu_irq_handler, 3748c2ecf20Sopenharmony_ci IRQF_SHARED, KBUILD_MODNAME "-gpu", pfdev); 3758c2ecf20Sopenharmony_ci if (err) { 3768c2ecf20Sopenharmony_ci dev_err(pfdev->dev, "failed to request gpu irq"); 3778c2ecf20Sopenharmony_ci return err; 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci panfrost_gpu_power_on(pfdev); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci return 0; 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_civoid panfrost_gpu_fini(struct panfrost_device *pfdev) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci panfrost_gpu_power_off(pfdev); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ciu32 panfrost_gpu_get_latest_flush_id(struct panfrost_device *pfdev) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci u32 flush_id; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci if (panfrost_has_hw_feature(pfdev, HW_FEATURE_FLUSH_REDUCTION)) { 3958c2ecf20Sopenharmony_ci /* Flush reduction only makes sense when the GPU is kept powered on between jobs */ 3968c2ecf20Sopenharmony_ci if (pm_runtime_get_if_in_use(pfdev->dev)) { 3978c2ecf20Sopenharmony_ci flush_id = gpu_read(pfdev, GPU_LATEST_FLUSH_ID); 3988c2ecf20Sopenharmony_ci pm_runtime_put(pfdev->dev); 3998c2ecf20Sopenharmony_ci return flush_id; 4008c2ecf20Sopenharmony_ci } 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci return 0; 4048c2ecf20Sopenharmony_ci} 405