18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2013-2014 Red Hat 48c2ecf20Sopenharmony_ci * Author: Rob Clark <robdclark@gmail.com> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "adreno_gpu.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#define ANY_ID 0xff 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cibool hang_debug = false; 148c2ecf20Sopenharmony_ciMODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)"); 158c2ecf20Sopenharmony_cimodule_param_named(hang_debug, hang_debug, bool, 0600); 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cibool snapshot_debugbus = false; 188c2ecf20Sopenharmony_ciMODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU devcoredump (if not fused off)"); 198c2ecf20Sopenharmony_cimodule_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic const struct adreno_info gpulist[] = { 228c2ecf20Sopenharmony_ci { 238c2ecf20Sopenharmony_ci .rev = ADRENO_REV(2, 0, 0, 0), 248c2ecf20Sopenharmony_ci .revn = 200, 258c2ecf20Sopenharmony_ci .name = "A200", 268c2ecf20Sopenharmony_ci .fw = { 278c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "yamato_pm4.fw", 288c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "yamato_pfp.fw", 298c2ecf20Sopenharmony_ci }, 308c2ecf20Sopenharmony_ci .gmem = SZ_256K, 318c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 328c2ecf20Sopenharmony_ci .init = a2xx_gpu_init, 338c2ecf20Sopenharmony_ci }, { /* a200 on i.mx51 has only 128kib gmem */ 348c2ecf20Sopenharmony_ci .rev = ADRENO_REV(2, 0, 0, 1), 358c2ecf20Sopenharmony_ci .revn = 201, 368c2ecf20Sopenharmony_ci .name = "A200", 378c2ecf20Sopenharmony_ci .fw = { 388c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "yamato_pm4.fw", 398c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "yamato_pfp.fw", 408c2ecf20Sopenharmony_ci }, 418c2ecf20Sopenharmony_ci .gmem = SZ_128K, 428c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 438c2ecf20Sopenharmony_ci .init = a2xx_gpu_init, 448c2ecf20Sopenharmony_ci }, { 458c2ecf20Sopenharmony_ci .rev = ADRENO_REV(2, 2, 0, ANY_ID), 468c2ecf20Sopenharmony_ci .revn = 220, 478c2ecf20Sopenharmony_ci .name = "A220", 488c2ecf20Sopenharmony_ci .fw = { 498c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "leia_pm4_470.fw", 508c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "leia_pfp_470.fw", 518c2ecf20Sopenharmony_ci }, 528c2ecf20Sopenharmony_ci .gmem = SZ_512K, 538c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 548c2ecf20Sopenharmony_ci .init = a2xx_gpu_init, 558c2ecf20Sopenharmony_ci }, { 568c2ecf20Sopenharmony_ci .rev = ADRENO_REV(3, 0, 5, ANY_ID), 578c2ecf20Sopenharmony_ci .revn = 305, 588c2ecf20Sopenharmony_ci .name = "A305", 598c2ecf20Sopenharmony_ci .fw = { 608c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a300_pm4.fw", 618c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a300_pfp.fw", 628c2ecf20Sopenharmony_ci }, 638c2ecf20Sopenharmony_ci .gmem = SZ_256K, 648c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 658c2ecf20Sopenharmony_ci .init = a3xx_gpu_init, 668c2ecf20Sopenharmony_ci }, { 678c2ecf20Sopenharmony_ci .rev = ADRENO_REV(3, 0, 6, 0), 688c2ecf20Sopenharmony_ci .revn = 307, /* because a305c is revn==306 */ 698c2ecf20Sopenharmony_ci .name = "A306", 708c2ecf20Sopenharmony_ci .fw = { 718c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a300_pm4.fw", 728c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a300_pfp.fw", 738c2ecf20Sopenharmony_ci }, 748c2ecf20Sopenharmony_ci .gmem = SZ_128K, 758c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 768c2ecf20Sopenharmony_ci .init = a3xx_gpu_init, 778c2ecf20Sopenharmony_ci }, { 788c2ecf20Sopenharmony_ci .rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID), 798c2ecf20Sopenharmony_ci .revn = 320, 808c2ecf20Sopenharmony_ci .name = "A320", 818c2ecf20Sopenharmony_ci .fw = { 828c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a300_pm4.fw", 838c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a300_pfp.fw", 848c2ecf20Sopenharmony_ci }, 858c2ecf20Sopenharmony_ci .gmem = SZ_512K, 868c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 878c2ecf20Sopenharmony_ci .init = a3xx_gpu_init, 888c2ecf20Sopenharmony_ci }, { 898c2ecf20Sopenharmony_ci .rev = ADRENO_REV(3, 3, 0, ANY_ID), 908c2ecf20Sopenharmony_ci .revn = 330, 918c2ecf20Sopenharmony_ci .name = "A330", 928c2ecf20Sopenharmony_ci .fw = { 938c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a330_pm4.fw", 948c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a330_pfp.fw", 958c2ecf20Sopenharmony_ci }, 968c2ecf20Sopenharmony_ci .gmem = SZ_1M, 978c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 988c2ecf20Sopenharmony_ci .init = a3xx_gpu_init, 998c2ecf20Sopenharmony_ci }, { 1008c2ecf20Sopenharmony_ci .rev = ADRENO_REV(4, 0, 5, ANY_ID), 1018c2ecf20Sopenharmony_ci .revn = 405, 1028c2ecf20Sopenharmony_ci .name = "A405", 1038c2ecf20Sopenharmony_ci .fw = { 1048c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a420_pm4.fw", 1058c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a420_pfp.fw", 1068c2ecf20Sopenharmony_ci }, 1078c2ecf20Sopenharmony_ci .gmem = SZ_256K, 1088c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 1098c2ecf20Sopenharmony_ci .init = a4xx_gpu_init, 1108c2ecf20Sopenharmony_ci }, { 1118c2ecf20Sopenharmony_ci .rev = ADRENO_REV(4, 2, 0, ANY_ID), 1128c2ecf20Sopenharmony_ci .revn = 420, 1138c2ecf20Sopenharmony_ci .name = "A420", 1148c2ecf20Sopenharmony_ci .fw = { 1158c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a420_pm4.fw", 1168c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a420_pfp.fw", 1178c2ecf20Sopenharmony_ci }, 1188c2ecf20Sopenharmony_ci .gmem = (SZ_1M + SZ_512K), 1198c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 1208c2ecf20Sopenharmony_ci .init = a4xx_gpu_init, 1218c2ecf20Sopenharmony_ci }, { 1228c2ecf20Sopenharmony_ci .rev = ADRENO_REV(4, 3, 0, ANY_ID), 1238c2ecf20Sopenharmony_ci .revn = 430, 1248c2ecf20Sopenharmony_ci .name = "A430", 1258c2ecf20Sopenharmony_ci .fw = { 1268c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a420_pm4.fw", 1278c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a420_pfp.fw", 1288c2ecf20Sopenharmony_ci }, 1298c2ecf20Sopenharmony_ci .gmem = (SZ_1M + SZ_512K), 1308c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 1318c2ecf20Sopenharmony_ci .init = a4xx_gpu_init, 1328c2ecf20Sopenharmony_ci }, { 1338c2ecf20Sopenharmony_ci .rev = ADRENO_REV(5, 1, 0, ANY_ID), 1348c2ecf20Sopenharmony_ci .revn = 510, 1358c2ecf20Sopenharmony_ci .name = "A510", 1368c2ecf20Sopenharmony_ci .fw = { 1378c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a530_pm4.fw", 1388c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a530_pfp.fw", 1398c2ecf20Sopenharmony_ci }, 1408c2ecf20Sopenharmony_ci .gmem = SZ_256K, 1418c2ecf20Sopenharmony_ci /* 1428c2ecf20Sopenharmony_ci * Increase inactive period to 250 to avoid bouncing 1438c2ecf20Sopenharmony_ci * the GDSC which appears to make it grumpy 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_ci .inactive_period = 250, 1468c2ecf20Sopenharmony_ci .init = a5xx_gpu_init, 1478c2ecf20Sopenharmony_ci }, { 1488c2ecf20Sopenharmony_ci .rev = ADRENO_REV(5, 3, 0, 2), 1498c2ecf20Sopenharmony_ci .revn = 530, 1508c2ecf20Sopenharmony_ci .name = "A530", 1518c2ecf20Sopenharmony_ci .fw = { 1528c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a530_pm4.fw", 1538c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a530_pfp.fw", 1548c2ecf20Sopenharmony_ci [ADRENO_FW_GPMU] = "a530v3_gpmu.fw2", 1558c2ecf20Sopenharmony_ci }, 1568c2ecf20Sopenharmony_ci .gmem = SZ_1M, 1578c2ecf20Sopenharmony_ci /* 1588c2ecf20Sopenharmony_ci * Increase inactive period to 250 to avoid bouncing 1598c2ecf20Sopenharmony_ci * the GDSC which appears to make it grumpy 1608c2ecf20Sopenharmony_ci */ 1618c2ecf20Sopenharmony_ci .inactive_period = 250, 1628c2ecf20Sopenharmony_ci .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI | 1638c2ecf20Sopenharmony_ci ADRENO_QUIRK_FAULT_DETECT_MASK, 1648c2ecf20Sopenharmony_ci .init = a5xx_gpu_init, 1658c2ecf20Sopenharmony_ci .zapfw = "a530_zap.mdt", 1668c2ecf20Sopenharmony_ci }, { 1678c2ecf20Sopenharmony_ci .rev = ADRENO_REV(5, 4, 0, 2), 1688c2ecf20Sopenharmony_ci .revn = 540, 1698c2ecf20Sopenharmony_ci .name = "A540", 1708c2ecf20Sopenharmony_ci .fw = { 1718c2ecf20Sopenharmony_ci [ADRENO_FW_PM4] = "a530_pm4.fw", 1728c2ecf20Sopenharmony_ci [ADRENO_FW_PFP] = "a530_pfp.fw", 1738c2ecf20Sopenharmony_ci [ADRENO_FW_GPMU] = "a540_gpmu.fw2", 1748c2ecf20Sopenharmony_ci }, 1758c2ecf20Sopenharmony_ci .gmem = SZ_1M, 1768c2ecf20Sopenharmony_ci /* 1778c2ecf20Sopenharmony_ci * Increase inactive period to 250 to avoid bouncing 1788c2ecf20Sopenharmony_ci * the GDSC which appears to make it grumpy 1798c2ecf20Sopenharmony_ci */ 1808c2ecf20Sopenharmony_ci .inactive_period = 250, 1818c2ecf20Sopenharmony_ci .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE, 1828c2ecf20Sopenharmony_ci .init = a5xx_gpu_init, 1838c2ecf20Sopenharmony_ci .zapfw = "a540_zap.mdt", 1848c2ecf20Sopenharmony_ci }, { 1858c2ecf20Sopenharmony_ci .rev = ADRENO_REV(6, 1, 8, ANY_ID), 1868c2ecf20Sopenharmony_ci .revn = 618, 1878c2ecf20Sopenharmony_ci .name = "A618", 1888c2ecf20Sopenharmony_ci .fw = { 1898c2ecf20Sopenharmony_ci [ADRENO_FW_SQE] = "a630_sqe.fw", 1908c2ecf20Sopenharmony_ci [ADRENO_FW_GMU] = "a630_gmu.bin", 1918c2ecf20Sopenharmony_ci }, 1928c2ecf20Sopenharmony_ci .gmem = SZ_512K, 1938c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 1948c2ecf20Sopenharmony_ci .init = a6xx_gpu_init, 1958c2ecf20Sopenharmony_ci }, { 1968c2ecf20Sopenharmony_ci .rev = ADRENO_REV(6, 3, 0, ANY_ID), 1978c2ecf20Sopenharmony_ci .revn = 630, 1988c2ecf20Sopenharmony_ci .name = "A630", 1998c2ecf20Sopenharmony_ci .fw = { 2008c2ecf20Sopenharmony_ci [ADRENO_FW_SQE] = "a630_sqe.fw", 2018c2ecf20Sopenharmony_ci [ADRENO_FW_GMU] = "a630_gmu.bin", 2028c2ecf20Sopenharmony_ci }, 2038c2ecf20Sopenharmony_ci .gmem = SZ_1M, 2048c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 2058c2ecf20Sopenharmony_ci .init = a6xx_gpu_init, 2068c2ecf20Sopenharmony_ci .zapfw = "a630_zap.mdt", 2078c2ecf20Sopenharmony_ci .hwcg = a630_hwcg, 2088c2ecf20Sopenharmony_ci }, { 2098c2ecf20Sopenharmony_ci .rev = ADRENO_REV(6, 4, 0, ANY_ID), 2108c2ecf20Sopenharmony_ci .revn = 640, 2118c2ecf20Sopenharmony_ci .name = "A640", 2128c2ecf20Sopenharmony_ci .fw = { 2138c2ecf20Sopenharmony_ci [ADRENO_FW_SQE] = "a630_sqe.fw", 2148c2ecf20Sopenharmony_ci [ADRENO_FW_GMU] = "a640_gmu.bin", 2158c2ecf20Sopenharmony_ci }, 2168c2ecf20Sopenharmony_ci .gmem = SZ_1M, 2178c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 2188c2ecf20Sopenharmony_ci .init = a6xx_gpu_init, 2198c2ecf20Sopenharmony_ci .zapfw = "a640_zap.mdt", 2208c2ecf20Sopenharmony_ci .hwcg = a640_hwcg, 2218c2ecf20Sopenharmony_ci }, { 2228c2ecf20Sopenharmony_ci .rev = ADRENO_REV(6, 5, 0, ANY_ID), 2238c2ecf20Sopenharmony_ci .revn = 650, 2248c2ecf20Sopenharmony_ci .name = "A650", 2258c2ecf20Sopenharmony_ci .fw = { 2268c2ecf20Sopenharmony_ci [ADRENO_FW_SQE] = "a650_sqe.fw", 2278c2ecf20Sopenharmony_ci [ADRENO_FW_GMU] = "a650_gmu.bin", 2288c2ecf20Sopenharmony_ci }, 2298c2ecf20Sopenharmony_ci .gmem = SZ_1M + SZ_128K, 2308c2ecf20Sopenharmony_ci .inactive_period = DRM_MSM_INACTIVE_PERIOD, 2318c2ecf20Sopenharmony_ci .init = a6xx_gpu_init, 2328c2ecf20Sopenharmony_ci .zapfw = "a650_zap.mdt", 2338c2ecf20Sopenharmony_ci .hwcg = a650_hwcg, 2348c2ecf20Sopenharmony_ci }, 2358c2ecf20Sopenharmony_ci}; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a300_pm4.fw"); 2388c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a300_pfp.fw"); 2398c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a330_pm4.fw"); 2408c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a330_pfp.fw"); 2418c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a420_pm4.fw"); 2428c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a420_pfp.fw"); 2438c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a530_pm4.fw"); 2448c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a530_pfp.fw"); 2458c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a530v3_gpmu.fw2"); 2468c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a530_zap.mdt"); 2478c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a530_zap.b00"); 2488c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a530_zap.b01"); 2498c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a530_zap.b02"); 2508c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a630_sqe.fw"); 2518c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a630_gmu.bin"); 2528c2ecf20Sopenharmony_ciMODULE_FIRMWARE("qcom/a630_zap.mbn"); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic inline bool _rev_match(uint8_t entry, uint8_t id) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci return (entry == ANY_ID) || (entry == id); 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ciconst struct adreno_info *adreno_info(struct adreno_rev rev) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci int i; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* identify gpu: */ 2648c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(gpulist); i++) { 2658c2ecf20Sopenharmony_ci const struct adreno_info *info = &gpulist[i]; 2668c2ecf20Sopenharmony_ci if (_rev_match(info->rev.core, rev.core) && 2678c2ecf20Sopenharmony_ci _rev_match(info->rev.major, rev.major) && 2688c2ecf20Sopenharmony_ci _rev_match(info->rev.minor, rev.minor) && 2698c2ecf20Sopenharmony_ci _rev_match(info->rev.patchid, rev.patchid)) 2708c2ecf20Sopenharmony_ci return info; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci return NULL; 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistruct msm_gpu *adreno_load_gpu(struct drm_device *dev) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci struct msm_drm_private *priv = dev->dev_private; 2798c2ecf20Sopenharmony_ci struct platform_device *pdev = priv->gpu_pdev; 2808c2ecf20Sopenharmony_ci struct msm_gpu *gpu = NULL; 2818c2ecf20Sopenharmony_ci struct adreno_gpu *adreno_gpu; 2828c2ecf20Sopenharmony_ci int ret; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if (pdev) 2858c2ecf20Sopenharmony_ci gpu = dev_to_gpu(&pdev->dev); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci if (!gpu) { 2888c2ecf20Sopenharmony_ci dev_err_once(dev->dev, "no GPU device was found\n"); 2898c2ecf20Sopenharmony_ci return NULL; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci adreno_gpu = to_adreno_gpu(gpu); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* 2958c2ecf20Sopenharmony_ci * The number one reason for HW init to fail is if the firmware isn't 2968c2ecf20Sopenharmony_ci * loaded yet. Try that first and don't bother continuing on 2978c2ecf20Sopenharmony_ci * otherwise 2988c2ecf20Sopenharmony_ci */ 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci ret = adreno_load_fw(adreno_gpu); 3018c2ecf20Sopenharmony_ci if (ret) 3028c2ecf20Sopenharmony_ci return NULL; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci /* 3058c2ecf20Sopenharmony_ci * Now that we have firmware loaded, and are ready to begin 3068c2ecf20Sopenharmony_ci * booting the gpu, go ahead and enable runpm: 3078c2ecf20Sopenharmony_ci */ 3088c2ecf20Sopenharmony_ci pm_runtime_enable(&pdev->dev); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci ret = pm_runtime_get_sync(&pdev->dev); 3118c2ecf20Sopenharmony_ci if (ret < 0) { 3128c2ecf20Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 3138c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev->dev, "Couldn't power up the GPU: %d\n", ret); 3148c2ecf20Sopenharmony_ci return NULL; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci mutex_lock(&dev->struct_mutex); 3188c2ecf20Sopenharmony_ci ret = msm_gpu_hw_init(gpu); 3198c2ecf20Sopenharmony_ci mutex_unlock(&dev->struct_mutex); 3208c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(&pdev->dev); 3218c2ecf20Sopenharmony_ci if (ret) { 3228c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev->dev, "gpu hw init failed: %d\n", ret); 3238c2ecf20Sopenharmony_ci return NULL; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 3278c2ecf20Sopenharmony_ci if (gpu->funcs->debugfs_init) { 3288c2ecf20Sopenharmony_ci gpu->funcs->debugfs_init(gpu, dev->primary); 3298c2ecf20Sopenharmony_ci gpu->funcs->debugfs_init(gpu, dev->render); 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci#endif 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci return gpu; 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic void set_gpu_pdev(struct drm_device *dev, 3378c2ecf20Sopenharmony_ci struct platform_device *pdev) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci struct msm_drm_private *priv = dev->dev_private; 3408c2ecf20Sopenharmony_ci priv->gpu_pdev = pdev; 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistatic int find_chipid(struct device *dev, struct adreno_rev *rev) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci struct device_node *node = dev->of_node; 3468c2ecf20Sopenharmony_ci const char *compat; 3478c2ecf20Sopenharmony_ci int ret; 3488c2ecf20Sopenharmony_ci u32 chipid; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* first search the compat strings for qcom,adreno-XYZ.W: */ 3518c2ecf20Sopenharmony_ci ret = of_property_read_string_index(node, "compatible", 0, &compat); 3528c2ecf20Sopenharmony_ci if (ret == 0) { 3538c2ecf20Sopenharmony_ci unsigned int r, patch; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci if (sscanf(compat, "qcom,adreno-%u.%u", &r, &patch) == 2 || 3568c2ecf20Sopenharmony_ci sscanf(compat, "amd,imageon-%u.%u", &r, &patch) == 2) { 3578c2ecf20Sopenharmony_ci rev->core = r / 100; 3588c2ecf20Sopenharmony_ci r %= 100; 3598c2ecf20Sopenharmony_ci rev->major = r / 10; 3608c2ecf20Sopenharmony_ci r %= 10; 3618c2ecf20Sopenharmony_ci rev->minor = r; 3628c2ecf20Sopenharmony_ci rev->patchid = patch; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci return 0; 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* and if that fails, fall back to legacy "qcom,chipid" property: */ 3698c2ecf20Sopenharmony_ci ret = of_property_read_u32(node, "qcom,chipid", &chipid); 3708c2ecf20Sopenharmony_ci if (ret) { 3718c2ecf20Sopenharmony_ci DRM_DEV_ERROR(dev, "could not parse qcom,chipid: %d\n", ret); 3728c2ecf20Sopenharmony_ci return ret; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci rev->core = (chipid >> 24) & 0xff; 3768c2ecf20Sopenharmony_ci rev->major = (chipid >> 16) & 0xff; 3778c2ecf20Sopenharmony_ci rev->minor = (chipid >> 8) & 0xff; 3788c2ecf20Sopenharmony_ci rev->patchid = (chipid & 0xff); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci dev_warn(dev, "Using legacy qcom,chipid binding!\n"); 3818c2ecf20Sopenharmony_ci dev_warn(dev, "Use compatible qcom,adreno-%u%u%u.%u instead.\n", 3828c2ecf20Sopenharmony_ci rev->core, rev->major, rev->minor, rev->patchid); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci return 0; 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic int adreno_bind(struct device *dev, struct device *master, void *data) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci static struct adreno_platform_config config = {}; 3908c2ecf20Sopenharmony_ci const struct adreno_info *info; 3918c2ecf20Sopenharmony_ci struct drm_device *drm = dev_get_drvdata(master); 3928c2ecf20Sopenharmony_ci struct msm_drm_private *priv = drm->dev_private; 3938c2ecf20Sopenharmony_ci struct msm_gpu *gpu; 3948c2ecf20Sopenharmony_ci int ret; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci ret = find_chipid(dev, &config.rev); 3978c2ecf20Sopenharmony_ci if (ret) 3988c2ecf20Sopenharmony_ci return ret; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci dev->platform_data = &config; 4018c2ecf20Sopenharmony_ci set_gpu_pdev(drm, to_platform_device(dev)); 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci info = adreno_info(config.rev); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci if (!info) { 4068c2ecf20Sopenharmony_ci dev_warn(drm->dev, "Unknown GPU revision: %u.%u.%u.%u\n", 4078c2ecf20Sopenharmony_ci config.rev.core, config.rev.major, 4088c2ecf20Sopenharmony_ci config.rev.minor, config.rev.patchid); 4098c2ecf20Sopenharmony_ci return -ENXIO; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci DBG("Found GPU: %u.%u.%u.%u", config.rev.core, config.rev.major, 4138c2ecf20Sopenharmony_ci config.rev.minor, config.rev.patchid); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci priv->is_a2xx = config.rev.core == 2; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci gpu = info->init(drm); 4188c2ecf20Sopenharmony_ci if (IS_ERR(gpu)) { 4198c2ecf20Sopenharmony_ci dev_warn(drm->dev, "failed to load adreno gpu\n"); 4208c2ecf20Sopenharmony_ci return PTR_ERR(gpu); 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci return 0; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic void adreno_unbind(struct device *dev, struct device *master, 4278c2ecf20Sopenharmony_ci void *data) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci struct msm_gpu *gpu = dev_to_gpu(dev); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci pm_runtime_force_suspend(dev); 4328c2ecf20Sopenharmony_ci gpu->funcs->destroy(gpu); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci set_gpu_pdev(dev_get_drvdata(master), NULL); 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistatic const struct component_ops a3xx_ops = { 4388c2ecf20Sopenharmony_ci .bind = adreno_bind, 4398c2ecf20Sopenharmony_ci .unbind = adreno_unbind, 4408c2ecf20Sopenharmony_ci}; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistatic void adreno_device_register_headless(void) 4438c2ecf20Sopenharmony_ci{ 4448c2ecf20Sopenharmony_ci /* on imx5, we don't have a top-level mdp/dpu node 4458c2ecf20Sopenharmony_ci * this creates a dummy node for the driver for that case 4468c2ecf20Sopenharmony_ci */ 4478c2ecf20Sopenharmony_ci struct platform_device_info dummy_info = { 4488c2ecf20Sopenharmony_ci .parent = NULL, 4498c2ecf20Sopenharmony_ci .name = "msm", 4508c2ecf20Sopenharmony_ci .id = -1, 4518c2ecf20Sopenharmony_ci .res = NULL, 4528c2ecf20Sopenharmony_ci .num_res = 0, 4538c2ecf20Sopenharmony_ci .data = NULL, 4548c2ecf20Sopenharmony_ci .size_data = 0, 4558c2ecf20Sopenharmony_ci .dma_mask = ~0, 4568c2ecf20Sopenharmony_ci }; 4578c2ecf20Sopenharmony_ci platform_device_register_full(&dummy_info); 4588c2ecf20Sopenharmony_ci} 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_cistatic int adreno_probe(struct platform_device *pdev) 4618c2ecf20Sopenharmony_ci{ 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci int ret; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci ret = component_add(&pdev->dev, &a3xx_ops); 4668c2ecf20Sopenharmony_ci if (ret) 4678c2ecf20Sopenharmony_ci return ret; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon")) 4708c2ecf20Sopenharmony_ci adreno_device_register_headless(); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci return 0; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic int adreno_remove(struct platform_device *pdev) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci component_del(&pdev->dev, &a3xx_ops); 4788c2ecf20Sopenharmony_ci return 0; 4798c2ecf20Sopenharmony_ci} 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_cistatic const struct of_device_id dt_match[] = { 4828c2ecf20Sopenharmony_ci { .compatible = "qcom,adreno" }, 4838c2ecf20Sopenharmony_ci { .compatible = "qcom,adreno-3xx" }, 4848c2ecf20Sopenharmony_ci /* for compatibility with imx5 gpu: */ 4858c2ecf20Sopenharmony_ci { .compatible = "amd,imageon" }, 4868c2ecf20Sopenharmony_ci /* for backwards compat w/ downstream kgsl DT files: */ 4878c2ecf20Sopenharmony_ci { .compatible = "qcom,kgsl-3d0" }, 4888c2ecf20Sopenharmony_ci {} 4898c2ecf20Sopenharmony_ci}; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 4928c2ecf20Sopenharmony_cistatic int adreno_resume(struct device *dev) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci struct msm_gpu *gpu = dev_to_gpu(dev); 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci return gpu->funcs->pm_resume(gpu); 4978c2ecf20Sopenharmony_ci} 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_cistatic int adreno_suspend(struct device *dev) 5008c2ecf20Sopenharmony_ci{ 5018c2ecf20Sopenharmony_ci struct msm_gpu *gpu = dev_to_gpu(dev); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci return gpu->funcs->pm_suspend(gpu); 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci#endif 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_cistatic const struct dev_pm_ops adreno_pm_ops = { 5088c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) 5098c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(adreno_suspend, adreno_resume, NULL) 5108c2ecf20Sopenharmony_ci}; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_cistatic struct platform_driver adreno_driver = { 5138c2ecf20Sopenharmony_ci .probe = adreno_probe, 5148c2ecf20Sopenharmony_ci .remove = adreno_remove, 5158c2ecf20Sopenharmony_ci .driver = { 5168c2ecf20Sopenharmony_ci .name = "adreno", 5178c2ecf20Sopenharmony_ci .of_match_table = dt_match, 5188c2ecf20Sopenharmony_ci .pm = &adreno_pm_ops, 5198c2ecf20Sopenharmony_ci }, 5208c2ecf20Sopenharmony_ci}; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_civoid __init adreno_register(void) 5238c2ecf20Sopenharmony_ci{ 5248c2ecf20Sopenharmony_ci platform_driver_register(&adreno_driver); 5258c2ecf20Sopenharmony_ci} 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_civoid __exit adreno_unregister(void) 5288c2ecf20Sopenharmony_ci{ 5298c2ecf20Sopenharmony_ci platform_driver_unregister(&adreno_driver); 5308c2ecf20Sopenharmony_ci} 531