adreno_device.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*
  2. * Copyright (C) 2013-2014 Red Hat
  3. * Author: Rob Clark <robdclark@gmail.com>
  4. *
  5. * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License version 2 as published by
  9. * the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along with
  17. * this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "adreno_gpu.h"
  20. #define ANY_ID 0xff
  21. bool hang_debug = false;
  22. MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
  23. module_param_named(hang_debug, hang_debug, bool, 0600);
  24. static const struct adreno_info gpulist[] = {
  25. {
  26. .rev = ADRENO_REV(3, 0, 5, ANY_ID),
  27. .revn = 305,
  28. .name = "A305",
  29. .fw = {
  30. [ADRENO_FW_PM4] = "a300_pm4.fw",
  31. [ADRENO_FW_PFP] = "a300_pfp.fw",
  32. },
  33. .gmem = SZ_256K,
  34. .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  35. .init = a3xx_gpu_init,
  36. }, {
  37. .rev = ADRENO_REV(3, 0, 6, 0),
  38. .revn = 307, /* because a305c is revn==306 */
  39. .name = "A306",
  40. .fw = {
  41. [ADRENO_FW_PM4] = "a300_pm4.fw",
  42. [ADRENO_FW_PFP] = "a300_pfp.fw",
  43. },
  44. .gmem = SZ_128K,
  45. .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  46. .init = a3xx_gpu_init,
  47. }, {
  48. .rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID),
  49. .revn = 320,
  50. .name = "A320",
  51. .fw = {
  52. [ADRENO_FW_PM4] = "a300_pm4.fw",
  53. [ADRENO_FW_PFP] = "a300_pfp.fw",
  54. },
  55. .gmem = SZ_512K,
  56. .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  57. .init = a3xx_gpu_init,
  58. }, {
  59. .rev = ADRENO_REV(3, 3, 0, ANY_ID),
  60. .revn = 330,
  61. .name = "A330",
  62. .fw = {
  63. [ADRENO_FW_PM4] = "a330_pm4.fw",
  64. [ADRENO_FW_PFP] = "a330_pfp.fw",
  65. },
  66. .gmem = SZ_1M,
  67. .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  68. .init = a3xx_gpu_init,
  69. }, {
  70. .rev = ADRENO_REV(4, 2, 0, ANY_ID),
  71. .revn = 420,
  72. .name = "A420",
  73. .fw = {
  74. [ADRENO_FW_PM4] = "a420_pm4.fw",
  75. [ADRENO_FW_PFP] = "a420_pfp.fw",
  76. },
  77. .gmem = (SZ_1M + SZ_512K),
  78. .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  79. .init = a4xx_gpu_init,
  80. }, {
  81. .rev = ADRENO_REV(4, 3, 0, ANY_ID),
  82. .revn = 430,
  83. .name = "A430",
  84. .fw = {
  85. [ADRENO_FW_PM4] = "a420_pm4.fw",
  86. [ADRENO_FW_PFP] = "a420_pfp.fw",
  87. },
  88. .gmem = (SZ_1M + SZ_512K),
  89. .inactive_period = DRM_MSM_INACTIVE_PERIOD,
  90. .init = a4xx_gpu_init,
  91. }, {
  92. .rev = ADRENO_REV(5, 3, 0, 2),
  93. .revn = 530,
  94. .name = "A530",
  95. .fw = {
  96. [ADRENO_FW_PM4] = "a530_pm4.fw",
  97. [ADRENO_FW_PFP] = "a530_pfp.fw",
  98. [ADRENO_FW_GPMU] = "a530v3_gpmu.fw2",
  99. },
  100. .gmem = SZ_1M,
  101. /*
  102. * Increase inactive period to 250 to avoid bouncing
  103. * the GDSC which appears to make it grumpy
  104. */
  105. .inactive_period = 250,
  106. .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI |
  107. ADRENO_QUIRK_FAULT_DETECT_MASK,
  108. .init = a5xx_gpu_init,
  109. .zapfw = "a530_zap.mdt",
  110. }, {
  111. .rev = ADRENO_REV(6, 3, 0, ANY_ID),
  112. .revn = 630,
  113. .name = "A630",
  114. .fw = {
  115. [ADRENO_FW_SQE] = "a630_sqe.fw",
  116. [ADRENO_FW_GMU] = "a630_gmu.bin",
  117. },
  118. .gmem = SZ_1M,
  119. .init = a6xx_gpu_init,
  120. },
  121. };
  122. MODULE_FIRMWARE("qcom/a300_pm4.fw");
  123. MODULE_FIRMWARE("qcom/a300_pfp.fw");
  124. MODULE_FIRMWARE("qcom/a330_pm4.fw");
  125. MODULE_FIRMWARE("qcom/a330_pfp.fw");
  126. MODULE_FIRMWARE("qcom/a420_pm4.fw");
  127. MODULE_FIRMWARE("qcom/a420_pfp.fw");
  128. MODULE_FIRMWARE("qcom/a530_pm4.fw");
  129. MODULE_FIRMWARE("qcom/a530_pfp.fw");
  130. MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2");
  131. MODULE_FIRMWARE("qcom/a530_zap.mdt");
  132. MODULE_FIRMWARE("qcom/a530_zap.b00");
  133. MODULE_FIRMWARE("qcom/a530_zap.b01");
  134. MODULE_FIRMWARE("qcom/a530_zap.b02");
  135. MODULE_FIRMWARE("qcom/a630_sqe.fw");
  136. MODULE_FIRMWARE("qcom/a630_gmu.bin");
  137. static inline bool _rev_match(uint8_t entry, uint8_t id)
  138. {
  139. return (entry == ANY_ID) || (entry == id);
  140. }
  141. const struct adreno_info *adreno_info(struct adreno_rev rev)
  142. {
  143. int i;
  144. /* identify gpu: */
  145. for (i = 0; i < ARRAY_SIZE(gpulist); i++) {
  146. const struct adreno_info *info = &gpulist[i];
  147. if (_rev_match(info->rev.core, rev.core) &&
  148. _rev_match(info->rev.major, rev.major) &&
  149. _rev_match(info->rev.minor, rev.minor) &&
  150. _rev_match(info->rev.patchid, rev.patchid))
  151. return info;
  152. }
  153. return NULL;
  154. }
  155. struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
  156. {
  157. struct msm_drm_private *priv = dev->dev_private;
  158. struct platform_device *pdev = priv->gpu_pdev;
  159. struct msm_gpu *gpu = NULL;
  160. struct adreno_gpu *adreno_gpu;
  161. int ret;
  162. if (pdev)
  163. gpu = platform_get_drvdata(pdev);
  164. if (!gpu) {
  165. dev_err_once(dev->dev, "no GPU device was found\n");
  166. return NULL;
  167. }
  168. adreno_gpu = to_adreno_gpu(gpu);
  169. /*
  170. * The number one reason for HW init to fail is if the firmware isn't
  171. * loaded yet. Try that first and don't bother continuing on
  172. * otherwise
  173. */
  174. ret = adreno_load_fw(adreno_gpu);
  175. if (ret)
  176. return NULL;
  177. /* Make sure pm runtime is active and reset any previous errors */
  178. pm_runtime_set_active(&pdev->dev);
  179. ret = pm_runtime_get_sync(&pdev->dev);
  180. if (ret < 0) {
  181. dev_err(dev->dev, "Couldn't power up the GPU: %d\n", ret);
  182. return NULL;
  183. }
  184. mutex_lock(&dev->struct_mutex);
  185. ret = msm_gpu_hw_init(gpu);
  186. mutex_unlock(&dev->struct_mutex);
  187. pm_runtime_put_autosuspend(&pdev->dev);
  188. if (ret) {
  189. dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
  190. return NULL;
  191. }
  192. #ifdef CONFIG_DEBUG_FS
  193. if (gpu->funcs->debugfs_init) {
  194. gpu->funcs->debugfs_init(gpu, dev->primary);
  195. gpu->funcs->debugfs_init(gpu, dev->render);
  196. }
  197. #endif
  198. return gpu;
  199. }
  200. static void set_gpu_pdev(struct drm_device *dev,
  201. struct platform_device *pdev)
  202. {
  203. struct msm_drm_private *priv = dev->dev_private;
  204. priv->gpu_pdev = pdev;
  205. }
  206. static int find_chipid(struct device *dev, struct adreno_rev *rev)
  207. {
  208. struct device_node *node = dev->of_node;
  209. const char *compat;
  210. int ret;
  211. u32 chipid;
  212. /* first search the compat strings for qcom,adreno-XYZ.W: */
  213. ret = of_property_read_string_index(node, "compatible", 0, &compat);
  214. if (ret == 0) {
  215. unsigned int r, patch;
  216. if (sscanf(compat, "qcom,adreno-%u.%u", &r, &patch) == 2) {
  217. rev->core = r / 100;
  218. r %= 100;
  219. rev->major = r / 10;
  220. r %= 10;
  221. rev->minor = r;
  222. rev->patchid = patch;
  223. return 0;
  224. }
  225. }
  226. /* and if that fails, fall back to legacy "qcom,chipid" property: */
  227. ret = of_property_read_u32(node, "qcom,chipid", &chipid);
  228. if (ret) {
  229. dev_err(dev, "could not parse qcom,chipid: %d\n", ret);
  230. return ret;
  231. }
  232. rev->core = (chipid >> 24) & 0xff;
  233. rev->major = (chipid >> 16) & 0xff;
  234. rev->minor = (chipid >> 8) & 0xff;
  235. rev->patchid = (chipid & 0xff);
  236. dev_warn(dev, "Using legacy qcom,chipid binding!\n");
  237. dev_warn(dev, "Use compatible qcom,adreno-%u%u%u.%u instead.\n",
  238. rev->core, rev->major, rev->minor, rev->patchid);
  239. return 0;
  240. }
  241. static int adreno_bind(struct device *dev, struct device *master, void *data)
  242. {
  243. static struct adreno_platform_config config = {};
  244. const struct adreno_info *info;
  245. struct drm_device *drm = dev_get_drvdata(master);
  246. struct msm_gpu *gpu;
  247. int ret;
  248. ret = find_chipid(dev, &config.rev);
  249. if (ret)
  250. return ret;
  251. dev->platform_data = &config;
  252. set_gpu_pdev(drm, to_platform_device(dev));
  253. info = adreno_info(config.rev);
  254. if (!info) {
  255. dev_warn(drm->dev, "Unknown GPU revision: %u.%u.%u.%u\n",
  256. config.rev.core, config.rev.major,
  257. config.rev.minor, config.rev.patchid);
  258. return -ENXIO;
  259. }
  260. DBG("Found GPU: %u.%u.%u.%u", config.rev.core, config.rev.major,
  261. config.rev.minor, config.rev.patchid);
  262. gpu = info->init(drm);
  263. if (IS_ERR(gpu)) {
  264. dev_warn(drm->dev, "failed to load adreno gpu\n");
  265. return PTR_ERR(gpu);
  266. }
  267. dev_set_drvdata(dev, gpu);
  268. return 0;
  269. }
  270. static void adreno_unbind(struct device *dev, struct device *master,
  271. void *data)
  272. {
  273. struct msm_gpu *gpu = dev_get_drvdata(dev);
  274. gpu->funcs->pm_suspend(gpu);
  275. gpu->funcs->destroy(gpu);
  276. set_gpu_pdev(dev_get_drvdata(master), NULL);
  277. }
  278. static const struct component_ops a3xx_ops = {
  279. .bind = adreno_bind,
  280. .unbind = adreno_unbind,
  281. };
  282. static int adreno_probe(struct platform_device *pdev)
  283. {
  284. return component_add(&pdev->dev, &a3xx_ops);
  285. }
  286. static int adreno_remove(struct platform_device *pdev)
  287. {
  288. component_del(&pdev->dev, &a3xx_ops);
  289. return 0;
  290. }
  291. static const struct of_device_id dt_match[] = {
  292. { .compatible = "qcom,adreno" },
  293. { .compatible = "qcom,adreno-3xx" },
  294. /* for backwards compat w/ downstream kgsl DT files: */
  295. { .compatible = "qcom,kgsl-3d0" },
  296. {}
  297. };
  298. #ifdef CONFIG_PM
  299. static int adreno_resume(struct device *dev)
  300. {
  301. struct platform_device *pdev = to_platform_device(dev);
  302. struct msm_gpu *gpu = platform_get_drvdata(pdev);
  303. return gpu->funcs->pm_resume(gpu);
  304. }
  305. static int adreno_suspend(struct device *dev)
  306. {
  307. struct platform_device *pdev = to_platform_device(dev);
  308. struct msm_gpu *gpu = platform_get_drvdata(pdev);
  309. return gpu->funcs->pm_suspend(gpu);
  310. }
  311. #endif
  312. static const struct dev_pm_ops adreno_pm_ops = {
  313. SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
  314. SET_RUNTIME_PM_OPS(adreno_suspend, adreno_resume, NULL)
  315. };
  316. static struct platform_driver adreno_driver = {
  317. .probe = adreno_probe,
  318. .remove = adreno_remove,
  319. .driver = {
  320. .name = "adreno",
  321. .of_match_table = dt_match,
  322. .pm = &adreno_pm_ops,
  323. },
  324. };
  325. void __init adreno_register(void)
  326. {
  327. platform_driver_register(&adreno_driver);
  328. }
  329. void __exit adreno_unregister(void)
  330. {
  331. platform_driver_unregister(&adreno_driver);
  332. }