1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2013-2014 Red Hat |
4 | * Author: Rob Clark <robdclark@gmail.com> |
5 | * |
6 | * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved. |
7 | */ |
8 | |
9 | #include "adreno_gpu.h" |
10 | |
11 | bool hang_debug = false; |
12 | MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)" ); |
13 | module_param_named(hang_debug, hang_debug, bool, 0600); |
14 | |
15 | bool snapshot_debugbus = false; |
16 | MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU devcoredump (if not fused off)" ); |
17 | module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600); |
18 | |
19 | bool allow_vram_carveout = false; |
20 | MODULE_PARM_DESC(allow_vram_carveout, "Allow using VRAM Carveout, in place of IOMMU" ); |
21 | module_param_named(allow_vram_carveout, allow_vram_carveout, bool, 0600); |
22 | |
23 | static const struct adreno_info gpulist[] = { |
24 | { |
25 | .chip_ids = ADRENO_CHIP_IDS(0x02000000), |
26 | .family = ADRENO_2XX_GEN1, |
27 | .revn = 200, |
28 | .fw = { |
29 | [ADRENO_FW_PM4] = "yamato_pm4.fw" , |
30 | [ADRENO_FW_PFP] = "yamato_pfp.fw" , |
31 | }, |
32 | .gmem = SZ_256K, |
33 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
34 | .init = a2xx_gpu_init, |
35 | }, { /* a200 on i.mx51 has only 128kib gmem */ |
36 | .chip_ids = ADRENO_CHIP_IDS(0x02000001), |
37 | .family = ADRENO_2XX_GEN1, |
38 | .revn = 201, |
39 | .fw = { |
40 | [ADRENO_FW_PM4] = "yamato_pm4.fw" , |
41 | [ADRENO_FW_PFP] = "yamato_pfp.fw" , |
42 | }, |
43 | .gmem = SZ_128K, |
44 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
45 | .init = a2xx_gpu_init, |
46 | }, { |
47 | .chip_ids = ADRENO_CHIP_IDS(0x02020000), |
48 | .family = ADRENO_2XX_GEN2, |
49 | .revn = 220, |
50 | .fw = { |
51 | [ADRENO_FW_PM4] = "leia_pm4_470.fw" , |
52 | [ADRENO_FW_PFP] = "leia_pfp_470.fw" , |
53 | }, |
54 | .gmem = SZ_512K, |
55 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
56 | .init = a2xx_gpu_init, |
57 | }, { |
58 | .chip_ids = ADRENO_CHIP_IDS(0x03000512), |
59 | .family = ADRENO_3XX, |
60 | .fw = { |
61 | [ADRENO_FW_PM4] = "a330_pm4.fw" , |
62 | [ADRENO_FW_PFP] = "a330_pfp.fw" , |
63 | }, |
64 | .gmem = SZ_128K, |
65 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
66 | .init = a3xx_gpu_init, |
67 | }, { |
68 | .chip_ids = ADRENO_CHIP_IDS(0x03000520), |
69 | .family = ADRENO_3XX, |
70 | .revn = 305, |
71 | .fw = { |
72 | [ADRENO_FW_PM4] = "a300_pm4.fw" , |
73 | [ADRENO_FW_PFP] = "a300_pfp.fw" , |
74 | }, |
75 | .gmem = SZ_256K, |
76 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
77 | .init = a3xx_gpu_init, |
78 | }, { |
79 | .chip_ids = ADRENO_CHIP_IDS(0x03000600), |
80 | .family = ADRENO_3XX, |
81 | .revn = 307, /* because a305c is revn==306 */ |
82 | .fw = { |
83 | [ADRENO_FW_PM4] = "a300_pm4.fw" , |
84 | [ADRENO_FW_PFP] = "a300_pfp.fw" , |
85 | }, |
86 | .gmem = SZ_128K, |
87 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
88 | .init = a3xx_gpu_init, |
89 | }, { |
90 | .chip_ids = ADRENO_CHIP_IDS( |
91 | 0x03020000, |
92 | 0x03020001, |
93 | 0x03020002 |
94 | ), |
95 | .family = ADRENO_3XX, |
96 | .revn = 320, |
97 | .fw = { |
98 | [ADRENO_FW_PM4] = "a300_pm4.fw" , |
99 | [ADRENO_FW_PFP] = "a300_pfp.fw" , |
100 | }, |
101 | .gmem = SZ_512K, |
102 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
103 | .init = a3xx_gpu_init, |
104 | }, { |
105 | .chip_ids = ADRENO_CHIP_IDS( |
106 | 0x03030000, |
107 | 0x03030001, |
108 | 0x03030002 |
109 | ), |
110 | .family = ADRENO_3XX, |
111 | .revn = 330, |
112 | .fw = { |
113 | [ADRENO_FW_PM4] = "a330_pm4.fw" , |
114 | [ADRENO_FW_PFP] = "a330_pfp.fw" , |
115 | }, |
116 | .gmem = SZ_1M, |
117 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
118 | .init = a3xx_gpu_init, |
119 | }, { |
120 | .chip_ids = ADRENO_CHIP_IDS(0x04000500), |
121 | .family = ADRENO_4XX, |
122 | .revn = 405, |
123 | .fw = { |
124 | [ADRENO_FW_PM4] = "a420_pm4.fw" , |
125 | [ADRENO_FW_PFP] = "a420_pfp.fw" , |
126 | }, |
127 | .gmem = SZ_256K, |
128 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
129 | .init = a4xx_gpu_init, |
130 | }, { |
131 | .chip_ids = ADRENO_CHIP_IDS(0x04020000), |
132 | .family = ADRENO_4XX, |
133 | .revn = 420, |
134 | .fw = { |
135 | [ADRENO_FW_PM4] = "a420_pm4.fw" , |
136 | [ADRENO_FW_PFP] = "a420_pfp.fw" , |
137 | }, |
138 | .gmem = (SZ_1M + SZ_512K), |
139 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
140 | .init = a4xx_gpu_init, |
141 | }, { |
142 | .chip_ids = ADRENO_CHIP_IDS(0x04030002), |
143 | .family = ADRENO_4XX, |
144 | .revn = 430, |
145 | .fw = { |
146 | [ADRENO_FW_PM4] = "a420_pm4.fw" , |
147 | [ADRENO_FW_PFP] = "a420_pfp.fw" , |
148 | }, |
149 | .gmem = (SZ_1M + SZ_512K), |
150 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
151 | .init = a4xx_gpu_init, |
152 | }, { |
153 | .chip_ids = ADRENO_CHIP_IDS(0x05000600), |
154 | .family = ADRENO_5XX, |
155 | .revn = 506, |
156 | .fw = { |
157 | [ADRENO_FW_PM4] = "a530_pm4.fw" , |
158 | [ADRENO_FW_PFP] = "a530_pfp.fw" , |
159 | }, |
160 | .gmem = (SZ_128K + SZ_8K), |
161 | /* |
162 | * Increase inactive period to 250 to avoid bouncing |
163 | * the GDSC which appears to make it grumpy |
164 | */ |
165 | .inactive_period = 250, |
166 | .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI | |
167 | ADRENO_QUIRK_LMLOADKILL_DISABLE, |
168 | .init = a5xx_gpu_init, |
169 | .zapfw = "a506_zap.mdt" , |
170 | }, { |
171 | .chip_ids = ADRENO_CHIP_IDS(0x05000800), |
172 | .family = ADRENO_5XX, |
173 | .revn = 508, |
174 | .fw = { |
175 | [ADRENO_FW_PM4] = "a530_pm4.fw" , |
176 | [ADRENO_FW_PFP] = "a530_pfp.fw" , |
177 | }, |
178 | .gmem = (SZ_128K + SZ_8K), |
179 | /* |
180 | * Increase inactive period to 250 to avoid bouncing |
181 | * the GDSC which appears to make it grumpy |
182 | */ |
183 | .inactive_period = 250, |
184 | .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE, |
185 | .init = a5xx_gpu_init, |
186 | .zapfw = "a508_zap.mdt" , |
187 | }, { |
188 | .chip_ids = ADRENO_CHIP_IDS(0x05000900), |
189 | .family = ADRENO_5XX, |
190 | .revn = 509, |
191 | .fw = { |
192 | [ADRENO_FW_PM4] = "a530_pm4.fw" , |
193 | [ADRENO_FW_PFP] = "a530_pfp.fw" , |
194 | }, |
195 | .gmem = (SZ_256K + SZ_16K), |
196 | /* |
197 | * Increase inactive period to 250 to avoid bouncing |
198 | * the GDSC which appears to make it grumpy |
199 | */ |
200 | .inactive_period = 250, |
201 | .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE, |
202 | .init = a5xx_gpu_init, |
203 | /* Adreno 509 uses the same ZAP as 512 */ |
204 | .zapfw = "a512_zap.mdt" , |
205 | }, { |
206 | .chip_ids = ADRENO_CHIP_IDS(0x05010000), |
207 | .family = ADRENO_5XX, |
208 | .revn = 510, |
209 | .fw = { |
210 | [ADRENO_FW_PM4] = "a530_pm4.fw" , |
211 | [ADRENO_FW_PFP] = "a530_pfp.fw" , |
212 | }, |
213 | .gmem = SZ_256K, |
214 | /* |
215 | * Increase inactive period to 250 to avoid bouncing |
216 | * the GDSC which appears to make it grumpy |
217 | */ |
218 | .inactive_period = 250, |
219 | .init = a5xx_gpu_init, |
220 | }, { |
221 | .chip_ids = ADRENO_CHIP_IDS(0x05010200), |
222 | .family = ADRENO_5XX, |
223 | .revn = 512, |
224 | .fw = { |
225 | [ADRENO_FW_PM4] = "a530_pm4.fw" , |
226 | [ADRENO_FW_PFP] = "a530_pfp.fw" , |
227 | }, |
228 | .gmem = (SZ_256K + SZ_16K), |
229 | /* |
230 | * Increase inactive period to 250 to avoid bouncing |
231 | * the GDSC which appears to make it grumpy |
232 | */ |
233 | .inactive_period = 250, |
234 | .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE, |
235 | .init = a5xx_gpu_init, |
236 | .zapfw = "a512_zap.mdt" , |
237 | }, { |
238 | .chip_ids = ADRENO_CHIP_IDS( |
239 | 0x05030002, |
240 | 0x05030004 |
241 | ), |
242 | .family = ADRENO_5XX, |
243 | .revn = 530, |
244 | .fw = { |
245 | [ADRENO_FW_PM4] = "a530_pm4.fw" , |
246 | [ADRENO_FW_PFP] = "a530_pfp.fw" , |
247 | [ADRENO_FW_GPMU] = "a530v3_gpmu.fw2" , |
248 | }, |
249 | .gmem = SZ_1M, |
250 | /* |
251 | * Increase inactive period to 250 to avoid bouncing |
252 | * the GDSC which appears to make it grumpy |
253 | */ |
254 | .inactive_period = 250, |
255 | .quirks = ADRENO_QUIRK_TWO_PASS_USE_WFI | |
256 | ADRENO_QUIRK_FAULT_DETECT_MASK, |
257 | .init = a5xx_gpu_init, |
258 | .zapfw = "a530_zap.mdt" , |
259 | }, { |
260 | .chip_ids = ADRENO_CHIP_IDS(0x05040001), |
261 | .family = ADRENO_5XX, |
262 | .revn = 540, |
263 | .fw = { |
264 | [ADRENO_FW_PM4] = "a530_pm4.fw" , |
265 | [ADRENO_FW_PFP] = "a530_pfp.fw" , |
266 | [ADRENO_FW_GPMU] = "a540_gpmu.fw2" , |
267 | }, |
268 | .gmem = SZ_1M, |
269 | /* |
270 | * Increase inactive period to 250 to avoid bouncing |
271 | * the GDSC which appears to make it grumpy |
272 | */ |
273 | .inactive_period = 250, |
274 | .quirks = ADRENO_QUIRK_LMLOADKILL_DISABLE, |
275 | .init = a5xx_gpu_init, |
276 | .zapfw = "a540_zap.mdt" , |
277 | }, { |
278 | .chip_ids = ADRENO_CHIP_IDS(0x06010000), |
279 | .family = ADRENO_6XX_GEN1, |
280 | .revn = 610, |
281 | .fw = { |
282 | [ADRENO_FW_SQE] = "a630_sqe.fw" , |
283 | }, |
284 | .gmem = (SZ_128K + SZ_4K), |
285 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
286 | .init = a6xx_gpu_init, |
287 | .zapfw = "a610_zap.mdt" , |
288 | .hwcg = a612_hwcg, |
289 | /* |
290 | * There are (at least) three SoCs implementing A610: SM6125 |
291 | * (trinket), SM6115 (bengal) and SM6225 (khaje). Trinket does |
292 | * not have speedbinning, as only a single SKU exists and we |
293 | * don't support khaje upstream yet. Hence, this matching |
294 | * table is only valid for bengal. |
295 | */ |
296 | .speedbins = ADRENO_SPEEDBINS( |
297 | { 0, 0 }, |
298 | { 206, 1 }, |
299 | { 200, 2 }, |
300 | { 157, 3 }, |
301 | { 127, 4 }, |
302 | ), |
303 | }, { |
304 | .machine = "qcom,sm7150" , |
305 | .chip_ids = ADRENO_CHIP_IDS(0x06010800), |
306 | .family = ADRENO_6XX_GEN1, |
307 | .fw = { |
308 | [ADRENO_FW_SQE] = "a630_sqe.fw" , |
309 | [ADRENO_FW_GMU] = "a630_gmu.bin" , |
310 | }, |
311 | .gmem = SZ_512K, |
312 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
313 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, |
314 | .init = a6xx_gpu_init, |
315 | .zapfw = "a615_zap.mbn" , |
316 | .hwcg = a615_hwcg, |
317 | .speedbins = ADRENO_SPEEDBINS( |
318 | { 0, 0 }, |
319 | { 128, 1 }, |
320 | { 146, 2 }, |
321 | { 167, 3 }, |
322 | { 172, 4 }, |
323 | ), |
324 | }, { |
325 | .chip_ids = ADRENO_CHIP_IDS(0x06010800), |
326 | .family = ADRENO_6XX_GEN1, |
327 | .revn = 618, |
328 | .fw = { |
329 | [ADRENO_FW_SQE] = "a630_sqe.fw" , |
330 | [ADRENO_FW_GMU] = "a630_gmu.bin" , |
331 | }, |
332 | .gmem = SZ_512K, |
333 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
334 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, |
335 | .init = a6xx_gpu_init, |
336 | .speedbins = ADRENO_SPEEDBINS( |
337 | { 0, 0 }, |
338 | { 169, 1 }, |
339 | { 174, 2 }, |
340 | ), |
341 | }, { |
342 | .machine = "qcom,sm4350" , |
343 | .chip_ids = ADRENO_CHIP_IDS(0x06010900), |
344 | .family = ADRENO_6XX_GEN1, |
345 | .revn = 619, |
346 | .fw = { |
347 | [ADRENO_FW_SQE] = "a630_sqe.fw" , |
348 | [ADRENO_FW_GMU] = "a619_gmu.bin" , |
349 | }, |
350 | .gmem = SZ_512K, |
351 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
352 | .init = a6xx_gpu_init, |
353 | .zapfw = "a615_zap.mdt" , |
354 | .hwcg = a615_hwcg, |
355 | .speedbins = ADRENO_SPEEDBINS( |
356 | { 0, 0 }, |
357 | { 138, 1 }, |
358 | { 92, 2 }, |
359 | ), |
360 | }, { |
361 | .machine = "qcom,sm6375" , |
362 | .chip_ids = ADRENO_CHIP_IDS(0x06010901), |
363 | .family = ADRENO_6XX_GEN1, |
364 | .revn = 619, |
365 | .fw = { |
366 | [ADRENO_FW_SQE] = "a630_sqe.fw" , |
367 | [ADRENO_FW_GMU] = "a619_gmu.bin" , |
368 | }, |
369 | .gmem = SZ_512K, |
370 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
371 | .init = a6xx_gpu_init, |
372 | .zapfw = "a615_zap.mdt" , |
373 | .hwcg = a615_hwcg, |
374 | .speedbins = ADRENO_SPEEDBINS( |
375 | { 0, 0 }, |
376 | { 190, 1 }, |
377 | { 177, 2 }, |
378 | ), |
379 | }, { |
380 | .chip_ids = ADRENO_CHIP_IDS(0x06010900), |
381 | .family = ADRENO_6XX_GEN1, |
382 | .revn = 619, |
383 | .fw = { |
384 | [ADRENO_FW_SQE] = "a630_sqe.fw" , |
385 | [ADRENO_FW_GMU] = "a619_gmu.bin" , |
386 | }, |
387 | .gmem = SZ_512K, |
388 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
389 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, |
390 | .init = a6xx_gpu_init, |
391 | .zapfw = "a615_zap.mdt" , |
392 | .hwcg = a615_hwcg, |
393 | .speedbins = ADRENO_SPEEDBINS( |
394 | { 0, 0 }, |
395 | { 120, 4 }, |
396 | { 138, 3 }, |
397 | { 169, 2 }, |
398 | { 180, 1 }, |
399 | ), |
400 | }, { |
401 | .chip_ids = ADRENO_CHIP_IDS( |
402 | 0x06030001, |
403 | 0x06030002 |
404 | ), |
405 | .family = ADRENO_6XX_GEN1, |
406 | .revn = 630, |
407 | .fw = { |
408 | [ADRENO_FW_SQE] = "a630_sqe.fw" , |
409 | [ADRENO_FW_GMU] = "a630_gmu.bin" , |
410 | }, |
411 | .gmem = SZ_1M, |
412 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
413 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, |
414 | .init = a6xx_gpu_init, |
415 | .zapfw = "a630_zap.mdt" , |
416 | .hwcg = a630_hwcg, |
417 | }, { |
418 | .chip_ids = ADRENO_CHIP_IDS(0x06040001), |
419 | .family = ADRENO_6XX_GEN2, |
420 | .revn = 640, |
421 | .fw = { |
422 | [ADRENO_FW_SQE] = "a630_sqe.fw" , |
423 | [ADRENO_FW_GMU] = "a640_gmu.bin" , |
424 | }, |
425 | .gmem = SZ_1M, |
426 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
427 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, |
428 | .init = a6xx_gpu_init, |
429 | .zapfw = "a640_zap.mdt" , |
430 | .hwcg = a640_hwcg, |
431 | .speedbins = ADRENO_SPEEDBINS( |
432 | { 0, 0 }, |
433 | { 1, 1 }, |
434 | ), |
435 | }, { |
436 | .chip_ids = ADRENO_CHIP_IDS(0x06050002), |
437 | .family = ADRENO_6XX_GEN3, |
438 | .revn = 650, |
439 | .fw = { |
440 | [ADRENO_FW_SQE] = "a650_sqe.fw" , |
441 | [ADRENO_FW_GMU] = "a650_gmu.bin" , |
442 | }, |
443 | .gmem = SZ_1M + SZ_128K, |
444 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
445 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | |
446 | ADRENO_QUIRK_HAS_HW_APRIV, |
447 | .init = a6xx_gpu_init, |
448 | .zapfw = "a650_zap.mdt" , |
449 | .hwcg = a650_hwcg, |
450 | .address_space_size = SZ_16G, |
451 | .speedbins = ADRENO_SPEEDBINS( |
452 | { 0, 0 }, |
453 | { 1, 1 }, |
454 | { 2, 3 }, /* Yep, 2 and 3 are swapped! :/ */ |
455 | { 3, 2 }, |
456 | ), |
457 | }, { |
458 | .chip_ids = ADRENO_CHIP_IDS(0x06060001), |
459 | .family = ADRENO_6XX_GEN4, |
460 | .revn = 660, |
461 | .fw = { |
462 | [ADRENO_FW_SQE] = "a660_sqe.fw" , |
463 | [ADRENO_FW_GMU] = "a660_gmu.bin" , |
464 | }, |
465 | .gmem = SZ_1M + SZ_512K, |
466 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
467 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | |
468 | ADRENO_QUIRK_HAS_HW_APRIV, |
469 | .init = a6xx_gpu_init, |
470 | .zapfw = "a660_zap.mdt" , |
471 | .hwcg = a660_hwcg, |
472 | .address_space_size = SZ_16G, |
473 | }, { |
474 | .chip_ids = ADRENO_CHIP_IDS(0x06030500), |
475 | .family = ADRENO_6XX_GEN4, |
476 | .fw = { |
477 | [ADRENO_FW_SQE] = "a660_sqe.fw" , |
478 | [ADRENO_FW_GMU] = "a660_gmu.bin" , |
479 | }, |
480 | .gmem = SZ_512K, |
481 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
482 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | |
483 | ADRENO_QUIRK_HAS_HW_APRIV, |
484 | .init = a6xx_gpu_init, |
485 | .zapfw = "a660_zap.mbn" , |
486 | .hwcg = a660_hwcg, |
487 | .address_space_size = SZ_16G, |
488 | .speedbins = ADRENO_SPEEDBINS( |
489 | { 0, 0 }, |
490 | { 117, 0 }, |
491 | { 172, 2 }, /* Called speedbin 1 downstream, but let's not break things! */ |
492 | { 190, 1 }, |
493 | ), |
494 | }, { |
495 | .chip_ids = ADRENO_CHIP_IDS(0x06080001), |
496 | .family = ADRENO_6XX_GEN2, |
497 | .revn = 680, |
498 | .fw = { |
499 | [ADRENO_FW_SQE] = "a630_sqe.fw" , |
500 | [ADRENO_FW_GMU] = "a640_gmu.bin" , |
501 | }, |
502 | .gmem = SZ_2M, |
503 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
504 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT, |
505 | .init = a6xx_gpu_init, |
506 | .zapfw = "a640_zap.mdt" , |
507 | .hwcg = a640_hwcg, |
508 | }, { |
509 | .chip_ids = ADRENO_CHIP_IDS(0x06090000), |
510 | .family = ADRENO_6XX_GEN4, |
511 | .fw = { |
512 | [ADRENO_FW_SQE] = "a660_sqe.fw" , |
513 | [ADRENO_FW_GMU] = "a660_gmu.bin" , |
514 | }, |
515 | .gmem = SZ_4M, |
516 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
517 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | |
518 | ADRENO_QUIRK_HAS_HW_APRIV, |
519 | .init = a6xx_gpu_init, |
520 | .zapfw = "a690_zap.mdt" , |
521 | .hwcg = a690_hwcg, |
522 | .address_space_size = SZ_16G, |
523 | }, { |
524 | .chip_ids = ADRENO_CHIP_IDS(0x07000200), |
525 | .family = ADRENO_6XX_GEN1, /* NOT a mistake! */ |
526 | .fw = { |
527 | [ADRENO_FW_SQE] = "a702_sqe.fw" , |
528 | }, |
529 | .gmem = SZ_128K, |
530 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
531 | .quirks = ADRENO_QUIRK_HAS_HW_APRIV, |
532 | .init = a6xx_gpu_init, |
533 | .zapfw = "a702_zap.mbn" , |
534 | .hwcg = a702_hwcg, |
535 | .speedbins = ADRENO_SPEEDBINS( |
536 | { 0, 0 }, |
537 | { 236, 1 }, |
538 | { 178, 2 }, |
539 | { 142, 3 }, |
540 | ), |
541 | }, { |
542 | .chip_ids = ADRENO_CHIP_IDS(0x07030001), |
543 | .family = ADRENO_7XX_GEN1, |
544 | .fw = { |
545 | [ADRENO_FW_SQE] = "a730_sqe.fw" , |
546 | [ADRENO_FW_GMU] = "gmu_gen70000.bin" , |
547 | }, |
548 | .gmem = SZ_2M, |
549 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
550 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | |
551 | ADRENO_QUIRK_HAS_HW_APRIV, |
552 | .init = a6xx_gpu_init, |
553 | .zapfw = "a730_zap.mdt" , |
554 | .hwcg = a730_hwcg, |
555 | .address_space_size = SZ_16G, |
556 | }, { |
557 | .chip_ids = ADRENO_CHIP_IDS(0x43050a01), /* "C510v2" */ |
558 | .family = ADRENO_7XX_GEN2, |
559 | .fw = { |
560 | [ADRENO_FW_SQE] = "a740_sqe.fw" , |
561 | [ADRENO_FW_GMU] = "gmu_gen70200.bin" , |
562 | }, |
563 | .gmem = 3 * SZ_1M, |
564 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
565 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | |
566 | ADRENO_QUIRK_HAS_HW_APRIV, |
567 | .init = a6xx_gpu_init, |
568 | .zapfw = "a740_zap.mdt" , |
569 | .hwcg = a740_hwcg, |
570 | .address_space_size = SZ_16G, |
571 | }, { |
572 | .chip_ids = ADRENO_CHIP_IDS(0x43051401), /* "C520v2" */ |
573 | .family = ADRENO_7XX_GEN3, |
574 | .fw = { |
575 | [ADRENO_FW_SQE] = "gen70900_sqe.fw" , |
576 | [ADRENO_FW_GMU] = "gmu_gen70900.bin" , |
577 | }, |
578 | .gmem = 3 * SZ_1M, |
579 | .inactive_period = DRM_MSM_INACTIVE_PERIOD, |
580 | .quirks = ADRENO_QUIRK_HAS_CACHED_COHERENT | |
581 | ADRENO_QUIRK_HAS_HW_APRIV, |
582 | .init = a6xx_gpu_init, |
583 | .zapfw = "gen70900_zap.mbn" , |
584 | .address_space_size = SZ_16G, |
585 | }, |
586 | }; |
587 | |
588 | MODULE_FIRMWARE("qcom/a300_pm4.fw" ); |
589 | MODULE_FIRMWARE("qcom/a300_pfp.fw" ); |
590 | MODULE_FIRMWARE("qcom/a330_pm4.fw" ); |
591 | MODULE_FIRMWARE("qcom/a330_pfp.fw" ); |
592 | MODULE_FIRMWARE("qcom/a420_pm4.fw" ); |
593 | MODULE_FIRMWARE("qcom/a420_pfp.fw" ); |
594 | MODULE_FIRMWARE("qcom/a530_pm4.fw" ); |
595 | MODULE_FIRMWARE("qcom/a530_pfp.fw" ); |
596 | MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2" ); |
597 | MODULE_FIRMWARE("qcom/a530_zap.mdt" ); |
598 | MODULE_FIRMWARE("qcom/a530_zap.b00" ); |
599 | MODULE_FIRMWARE("qcom/a530_zap.b01" ); |
600 | MODULE_FIRMWARE("qcom/a530_zap.b02" ); |
601 | MODULE_FIRMWARE("qcom/a540_gpmu.fw2" ); |
602 | MODULE_FIRMWARE("qcom/a615_zap.mbn" ); |
603 | MODULE_FIRMWARE("qcom/a619_gmu.bin" ); |
604 | MODULE_FIRMWARE("qcom/a630_sqe.fw" ); |
605 | MODULE_FIRMWARE("qcom/a630_gmu.bin" ); |
606 | MODULE_FIRMWARE("qcom/a630_zap.mbn" ); |
607 | MODULE_FIRMWARE("qcom/a640_gmu.bin" ); |
608 | MODULE_FIRMWARE("qcom/a650_gmu.bin" ); |
609 | MODULE_FIRMWARE("qcom/a650_sqe.fw" ); |
610 | MODULE_FIRMWARE("qcom/a660_gmu.bin" ); |
611 | MODULE_FIRMWARE("qcom/a660_sqe.fw" ); |
612 | MODULE_FIRMWARE("qcom/leia_pfp_470.fw" ); |
613 | MODULE_FIRMWARE("qcom/leia_pm4_470.fw" ); |
614 | MODULE_FIRMWARE("qcom/yamato_pfp.fw" ); |
615 | MODULE_FIRMWARE("qcom/yamato_pm4.fw" ); |
616 | |
617 | static const struct adreno_info *adreno_info(uint32_t chip_id) |
618 | { |
619 | /* identify gpu: */ |
620 | for (int i = 0; i < ARRAY_SIZE(gpulist); i++) { |
621 | const struct adreno_info *info = &gpulist[i]; |
622 | if (info->machine && !of_machine_is_compatible(info->machine)) |
623 | continue; |
624 | for (int j = 0; info->chip_ids[j]; j++) |
625 | if (info->chip_ids[j] == chip_id) |
626 | return info; |
627 | } |
628 | |
629 | return NULL; |
630 | } |
631 | |
632 | struct msm_gpu *adreno_load_gpu(struct drm_device *dev) |
633 | { |
634 | struct msm_drm_private *priv = dev->dev_private; |
635 | struct platform_device *pdev = priv->gpu_pdev; |
636 | struct msm_gpu *gpu = NULL; |
637 | struct adreno_gpu *adreno_gpu; |
638 | int ret; |
639 | |
640 | if (pdev) |
641 | gpu = dev_to_gpu(&pdev->dev); |
642 | |
643 | if (!gpu) { |
644 | dev_err_once(dev->dev, "no GPU device was found\n" ); |
645 | return NULL; |
646 | } |
647 | |
648 | adreno_gpu = to_adreno_gpu(gpu); |
649 | |
650 | /* |
651 | * The number one reason for HW init to fail is if the firmware isn't |
652 | * loaded yet. Try that first and don't bother continuing on |
653 | * otherwise |
654 | */ |
655 | |
656 | ret = adreno_load_fw(adreno_gpu); |
657 | if (ret) |
658 | return NULL; |
659 | |
660 | if (gpu->funcs->ucode_load) { |
661 | ret = gpu->funcs->ucode_load(gpu); |
662 | if (ret) |
663 | return NULL; |
664 | } |
665 | |
666 | /* |
667 | * Now that we have firmware loaded, and are ready to begin |
668 | * booting the gpu, go ahead and enable runpm: |
669 | */ |
670 | pm_runtime_enable(&pdev->dev); |
671 | |
672 | ret = pm_runtime_get_sync(&pdev->dev); |
673 | if (ret < 0) { |
674 | pm_runtime_put_noidle(&pdev->dev); |
675 | DRM_DEV_ERROR(dev->dev, "Couldn't power up the GPU: %d\n" , ret); |
676 | goto err_disable_rpm; |
677 | } |
678 | |
679 | mutex_lock(&gpu->lock); |
680 | ret = msm_gpu_hw_init(gpu); |
681 | mutex_unlock(lock: &gpu->lock); |
682 | if (ret) { |
683 | DRM_DEV_ERROR(dev->dev, "gpu hw init failed: %d\n" , ret); |
684 | goto err_put_rpm; |
685 | } |
686 | |
687 | pm_runtime_put_autosuspend(&pdev->dev); |
688 | |
689 | #ifdef CONFIG_DEBUG_FS |
690 | if (gpu->funcs->debugfs_init) { |
691 | gpu->funcs->debugfs_init(gpu, dev->primary); |
692 | gpu->funcs->debugfs_init(gpu, dev->render); |
693 | } |
694 | #endif |
695 | |
696 | return gpu; |
697 | |
698 | err_put_rpm: |
699 | pm_runtime_put_sync_suspend(&pdev->dev); |
700 | err_disable_rpm: |
701 | pm_runtime_disable(&pdev->dev); |
702 | |
703 | return NULL; |
704 | } |
705 | |
706 | static int find_chipid(struct device *dev, uint32_t *chipid) |
707 | { |
708 | struct device_node *node = dev->of_node; |
709 | const char *compat; |
710 | int ret; |
711 | |
712 | /* first search the compat strings for qcom,adreno-XYZ.W: */ |
713 | ret = of_property_read_string_index(node, "compatible" , 0, &compat); |
714 | if (ret == 0) { |
715 | unsigned int r, patch; |
716 | |
717 | if (sscanf(compat, "qcom,adreno-%u.%u" , &r, &patch) == 2 || |
718 | sscanf(compat, "amd,imageon-%u.%u" , &r, &patch) == 2) { |
719 | uint32_t core, major, minor; |
720 | |
721 | core = r / 100; |
722 | r %= 100; |
723 | major = r / 10; |
724 | r %= 10; |
725 | minor = r; |
726 | |
727 | *chipid = (core << 24) | |
728 | (major << 16) | |
729 | (minor << 8) | |
730 | patch; |
731 | |
732 | return 0; |
733 | } |
734 | |
735 | if (sscanf(compat, "qcom,adreno-%08x" , chipid) == 1) |
736 | return 0; |
737 | } |
738 | |
739 | /* and if that fails, fall back to legacy "qcom,chipid" property: */ |
740 | ret = of_property_read_u32(node, "qcom,chipid" , chipid); |
741 | if (ret) { |
742 | DRM_DEV_ERROR(dev, "could not parse qcom,chipid: %d\n" , ret); |
743 | return ret; |
744 | } |
745 | |
746 | dev_warn(dev, "Using legacy qcom,chipid binding!\n" ); |
747 | |
748 | return 0; |
749 | } |
750 | |
751 | static int adreno_bind(struct device *dev, struct device *master, void *data) |
752 | { |
753 | static struct adreno_platform_config config = {}; |
754 | const struct adreno_info *info; |
755 | struct msm_drm_private *priv = dev_get_drvdata(master); |
756 | struct drm_device *drm = priv->dev; |
757 | struct msm_gpu *gpu; |
758 | int ret; |
759 | |
760 | ret = find_chipid(dev, chipid: &config.chip_id); |
761 | if (ret) |
762 | return ret; |
763 | |
764 | dev->platform_data = &config; |
765 | priv->gpu_pdev = to_platform_device(dev); |
766 | |
767 | info = adreno_info(chip_id: config.chip_id); |
768 | if (!info) { |
769 | dev_warn(drm->dev, "Unknown GPU revision: %" ADRENO_CHIPID_FMT"\n" , |
770 | ADRENO_CHIPID_ARGS(config.chip_id)); |
771 | return -ENXIO; |
772 | } |
773 | |
774 | config.info = info; |
775 | |
776 | DBG("Found GPU: %" ADRENO_CHIPID_FMT, ADRENO_CHIPID_ARGS(config.chip_id)); |
777 | |
778 | priv->is_a2xx = info->family < ADRENO_3XX; |
779 | priv->has_cached_coherent = |
780 | !!(info->quirks & ADRENO_QUIRK_HAS_CACHED_COHERENT); |
781 | |
782 | gpu = info->init(drm); |
783 | if (IS_ERR(ptr: gpu)) { |
784 | dev_warn(drm->dev, "failed to load adreno gpu\n" ); |
785 | return PTR_ERR(ptr: gpu); |
786 | } |
787 | |
788 | ret = dev_pm_opp_of_find_icc_paths(dev, NULL); |
789 | if (ret) |
790 | return ret; |
791 | |
792 | return 0; |
793 | } |
794 | |
795 | static int adreno_system_suspend(struct device *dev); |
796 | static void adreno_unbind(struct device *dev, struct device *master, |
797 | void *data) |
798 | { |
799 | struct msm_drm_private *priv = dev_get_drvdata(master); |
800 | struct msm_gpu *gpu = dev_to_gpu(dev); |
801 | |
802 | if (pm_runtime_enabled(dev)) |
803 | WARN_ON_ONCE(adreno_system_suspend(dev)); |
804 | gpu->funcs->destroy(gpu); |
805 | |
806 | priv->gpu_pdev = NULL; |
807 | } |
808 | |
809 | static const struct component_ops a3xx_ops = { |
810 | .bind = adreno_bind, |
811 | .unbind = adreno_unbind, |
812 | }; |
813 | |
814 | static void adreno_device_register_headless(void) |
815 | { |
816 | /* on imx5, we don't have a top-level mdp/dpu node |
817 | * this creates a dummy node for the driver for that case |
818 | */ |
819 | struct platform_device_info dummy_info = { |
820 | .parent = NULL, |
821 | .name = "msm" , |
822 | .id = -1, |
823 | .res = NULL, |
824 | .num_res = 0, |
825 | .data = NULL, |
826 | .size_data = 0, |
827 | .dma_mask = ~0, |
828 | }; |
829 | platform_device_register_full(&dummy_info); |
830 | } |
831 | |
832 | static int adreno_probe(struct platform_device *pdev) |
833 | { |
834 | |
835 | int ret; |
836 | |
837 | ret = component_add(&pdev->dev, &a3xx_ops); |
838 | if (ret) |
839 | return ret; |
840 | |
841 | if (of_device_is_compatible(pdev->dev.of_node, "amd,imageon" )) |
842 | adreno_device_register_headless(); |
843 | |
844 | return 0; |
845 | } |
846 | |
847 | static void adreno_remove(struct platform_device *pdev) |
848 | { |
849 | component_del(&pdev->dev, &a3xx_ops); |
850 | } |
851 | |
852 | static void adreno_shutdown(struct platform_device *pdev) |
853 | { |
854 | WARN_ON_ONCE(adreno_system_suspend(&pdev->dev)); |
855 | } |
856 | |
857 | static const struct of_device_id dt_match[] = { |
858 | { .compatible = "qcom,adreno" }, |
859 | { .compatible = "qcom,adreno-3xx" }, |
860 | /* for compatibility with imx5 gpu: */ |
861 | { .compatible = "amd,imageon" }, |
862 | /* for backwards compat w/ downstream kgsl DT files: */ |
863 | { .compatible = "qcom,kgsl-3d0" }, |
864 | {} |
865 | }; |
866 | |
867 | static int adreno_runtime_resume(struct device *dev) |
868 | { |
869 | struct msm_gpu *gpu = dev_to_gpu(dev); |
870 | |
871 | return gpu->funcs->pm_resume(gpu); |
872 | } |
873 | |
874 | static int adreno_runtime_suspend(struct device *dev) |
875 | { |
876 | struct msm_gpu *gpu = dev_to_gpu(dev); |
877 | |
878 | /* |
879 | * We should be holding a runpm ref, which will prevent |
880 | * runtime suspend. In the system suspend path, we've |
881 | * already waited for active jobs to complete. |
882 | */ |
883 | WARN_ON_ONCE(gpu->active_submits); |
884 | |
885 | return gpu->funcs->pm_suspend(gpu); |
886 | } |
887 | |
888 | static void suspend_scheduler(struct msm_gpu *gpu) |
889 | { |
890 | int i; |
891 | |
892 | /* |
893 | * Shut down the scheduler before we force suspend, so that |
894 | * suspend isn't racing with scheduler kthread feeding us |
895 | * more work. |
896 | * |
897 | * Note, we just want to park the thread, and let any jobs |
898 | * that are already on the hw queue complete normally, as |
899 | * opposed to the drm_sched_stop() path used for handling |
900 | * faulting/timed-out jobs. We can't really cancel any jobs |
901 | * already on the hw queue without racing with the GPU. |
902 | */ |
903 | for (i = 0; i < gpu->nr_rings; i++) { |
904 | struct drm_gpu_scheduler *sched = &gpu->rb[i]->sched; |
905 | |
906 | drm_sched_wqueue_stop(sched); |
907 | } |
908 | } |
909 | |
910 | static void resume_scheduler(struct msm_gpu *gpu) |
911 | { |
912 | int i; |
913 | |
914 | for (i = 0; i < gpu->nr_rings; i++) { |
915 | struct drm_gpu_scheduler *sched = &gpu->rb[i]->sched; |
916 | |
917 | drm_sched_wqueue_start(sched); |
918 | } |
919 | } |
920 | |
921 | static int adreno_system_suspend(struct device *dev) |
922 | { |
923 | struct msm_gpu *gpu = dev_to_gpu(dev); |
924 | int remaining, ret; |
925 | |
926 | if (!gpu) |
927 | return 0; |
928 | |
929 | suspend_scheduler(gpu); |
930 | |
931 | remaining = wait_event_timeout(gpu->retire_event, |
932 | gpu->active_submits == 0, |
933 | msecs_to_jiffies(1000)); |
934 | if (remaining == 0) { |
935 | dev_err(dev, "Timeout waiting for GPU to suspend\n" ); |
936 | ret = -EBUSY; |
937 | goto out; |
938 | } |
939 | |
940 | ret = pm_runtime_force_suspend(dev); |
941 | out: |
942 | if (ret) |
943 | resume_scheduler(gpu); |
944 | |
945 | return ret; |
946 | } |
947 | |
948 | static int adreno_system_resume(struct device *dev) |
949 | { |
950 | struct msm_gpu *gpu = dev_to_gpu(dev); |
951 | |
952 | if (!gpu) |
953 | return 0; |
954 | |
955 | resume_scheduler(gpu); |
956 | return pm_runtime_force_resume(dev); |
957 | } |
958 | |
959 | static const struct dev_pm_ops adreno_pm_ops = { |
960 | SYSTEM_SLEEP_PM_OPS(adreno_system_suspend, adreno_system_resume) |
961 | RUNTIME_PM_OPS(adreno_runtime_suspend, adreno_runtime_resume, NULL) |
962 | }; |
963 | |
964 | static struct platform_driver adreno_driver = { |
965 | .probe = adreno_probe, |
966 | .remove_new = adreno_remove, |
967 | .shutdown = adreno_shutdown, |
968 | .driver = { |
969 | .name = "adreno" , |
970 | .of_match_table = dt_match, |
971 | .pm = &adreno_pm_ops, |
972 | }, |
973 | }; |
974 | |
975 | void __init adreno_register(void) |
976 | { |
977 | platform_driver_register(&adreno_driver); |
978 | } |
979 | |
980 | void __exit adreno_unregister(void) |
981 | { |
982 | platform_driver_unregister(&adreno_driver); |
983 | } |
984 | |