1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3 *
4 * (C) COPYRIGHT 2012-2021 ARM Limited. All rights reserved.
5 *
6 * This program is free software and is provided to you under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation, and any use by you of this program is subject to the terms
9 * of such GNU license.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you can access it online at
18 * http://www.gnu.org/licenses/gpl-2.0.html.
19 *
20 */
21
22 /*
23 * Run-time work-arounds helpers
24 */
25
26 #include <mali_base_hwconfig_features.h>
27 #include <mali_base_hwconfig_issues.h>
28 #include "gpu/mali_kbase_gpu_regmap.h"
29 #include "mali_kbase.h"
30 #include "mali_kbase_hw.h"
31
kbase_hw_set_features_mask(struct kbase_device * kbdev)32 void kbase_hw_set_features_mask(struct kbase_device *kbdev)
33 {
34 const enum base_hw_feature *features;
35 u32 gpu_id;
36
37 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id;
38
39 switch (gpu_id & GPU_ID2_PRODUCT_MODEL) {
40 case GPU_ID2_PRODUCT_TMIX:
41 features = base_hw_features_tMIx;
42 break;
43 case GPU_ID2_PRODUCT_THEX:
44 features = base_hw_features_tHEx;
45 break;
46 case GPU_ID2_PRODUCT_TSIX:
47 features = base_hw_features_tSIx;
48 break;
49 case GPU_ID2_PRODUCT_TDVX:
50 features = base_hw_features_tDVx;
51 break;
52 case GPU_ID2_PRODUCT_TNOX:
53 features = base_hw_features_tNOx;
54 break;
55 case GPU_ID2_PRODUCT_TGOX:
56 features = base_hw_features_tGOx;
57 break;
58 case GPU_ID2_PRODUCT_TTRX:
59 features = base_hw_features_tTRx;
60 break;
61 case GPU_ID2_PRODUCT_TNAX:
62 features = base_hw_features_tNAx;
63 break;
64 case GPU_ID2_PRODUCT_LBEX:
65 case GPU_ID2_PRODUCT_TBEX:
66 features = base_hw_features_tBEx;
67 break;
68 case GPU_ID2_PRODUCT_TBAX:
69 features = base_hw_features_tBAx;
70 break;
71 case GPU_ID2_PRODUCT_TDUX:
72 features = base_hw_features_tDUx;
73 break;
74 case GPU_ID2_PRODUCT_TODX:
75 case GPU_ID2_PRODUCT_LODX:
76 features = base_hw_features_tODx;
77 break;
78 case GPU_ID2_PRODUCT_TGRX:
79 features = base_hw_features_tGRx;
80 break;
81 case GPU_ID2_PRODUCT_TVAX:
82 features = base_hw_features_tVAx;
83 break;
84 case GPU_ID2_PRODUCT_TTUX:
85 case GPU_ID2_PRODUCT_LTUX:
86 features = base_hw_features_tTUx;
87 break;
88 default:
89 features = base_hw_features_generic;
90 break;
91 }
92
93 for (; *features != BASE_HW_FEATURE_END; features++)
94 set_bit(*features, &kbdev->hw_features_mask[0]);
95
96 #if defined(CONFIG_MALI_VECTOR_DUMP)
97 /* When dumping is enabled, need to disable flush reduction optimization
98 * for GPUs on which it is safe to have only cache clean operation at
99 * the end of job chain.
100 * This is required to make vector dump work. There is some discrepancy
101 * in the implementation of flush reduction optimization due to
102 * unclear or ambiguous ARCH spec.
103 */
104 if (kbase_hw_has_feature(kbdev, BASE_HW_FEATURE_CLEAN_ONLY_SAFE))
105 clear_bit(BASE_HW_FEATURE_FLUSH_REDUCTION,
106 &kbdev->hw_features_mask[0]);
107 #endif
108 }
109
110 /**
111 * kbase_hw_get_issues_for_new_id - Get the hardware issues for a new GPU ID
112 * @kbdev: Device pointer
113 *
114 * Return: pointer to an array of hardware issues, terminated by
115 * BASE_HW_ISSUE_END.
116 *
117 * In debugging versions of the driver, unknown versions of a known GPU will
118 * be treated as the most recent known version not later than the actual
119 * version. In such circumstances, the GPU ID in @kbdev will also be replaced
120 * with the most recent known version.
121 *
122 * Note: The GPU configuration must have been read by kbase_gpuprops_get_props()
123 * before calling this function.
124 */
kbase_hw_get_issues_for_new_id(struct kbase_device * kbdev)125 static const enum base_hw_issue *kbase_hw_get_issues_for_new_id(
126 struct kbase_device *kbdev)
127 {
128 const enum base_hw_issue *issues = NULL;
129
130 struct base_hw_product {
131 u32 product_model;
132 struct {
133 u32 version;
134 const enum base_hw_issue *issues;
135 } map[7];
136 };
137
138 static const struct base_hw_product base_hw_products[] = {
139 { GPU_ID2_PRODUCT_TMIX,
140 { { GPU_ID2_VERSION_MAKE(0, 0, 1),
141 base_hw_issues_tMIx_r0p0_05dev0 },
142 { GPU_ID2_VERSION_MAKE(0, 0, 2), base_hw_issues_tMIx_r0p0 },
143 { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tMIx_r0p1 },
144 { U32_MAX /* sentinel value */, NULL } } },
145
146 { GPU_ID2_PRODUCT_THEX,
147 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tHEx_r0p0 },
148 { GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tHEx_r0p0 },
149 { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tHEx_r0p1 },
150 { GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tHEx_r0p1 },
151 { GPU_ID2_VERSION_MAKE(0, 2, 0), base_hw_issues_tHEx_r0p2 },
152 { GPU_ID2_VERSION_MAKE(0, 3, 0), base_hw_issues_tHEx_r0p3 },
153 { U32_MAX, NULL } } },
154
155 { GPU_ID2_PRODUCT_TSIX,
156 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tSIx_r0p0 },
157 { GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tSIx_r0p0 },
158 { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tSIx_r0p1 },
159 { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tSIx_r1p0 },
160 { GPU_ID2_VERSION_MAKE(1, 1, 0), base_hw_issues_tSIx_r1p1 },
161 { U32_MAX, NULL } } },
162
163 { GPU_ID2_PRODUCT_TDVX,
164 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tDVx_r0p0 },
165 { U32_MAX, NULL } } },
166
167 { GPU_ID2_PRODUCT_TNOX,
168 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tNOx_r0p0 },
169 { U32_MAX, NULL } } },
170
171 { GPU_ID2_PRODUCT_TGOX,
172 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tGOx_r0p0 },
173 { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tGOx_r1p0 },
174 { U32_MAX, NULL } } },
175
176 { GPU_ID2_PRODUCT_TTRX,
177 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTRx_r0p0 },
178 { GPU_ID2_VERSION_MAKE(0, 0, 3), base_hw_issues_tTRx_r0p0 },
179 { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tTRx_r0p1 },
180 { GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tTRx_r0p1 },
181 { GPU_ID2_VERSION_MAKE(0, 2, 0), base_hw_issues_tTRx_r0p2 },
182 { U32_MAX, NULL } } },
183
184 { GPU_ID2_PRODUCT_TNAX,
185 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tNAx_r0p0 },
186 { GPU_ID2_VERSION_MAKE(0, 0, 3), base_hw_issues_tNAx_r0p0 },
187 { GPU_ID2_VERSION_MAKE(0, 0, 4), base_hw_issues_tNAx_r0p0 },
188 { GPU_ID2_VERSION_MAKE(0, 0, 5), base_hw_issues_tNAx_r0p0 },
189 { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tNAx_r0p1 },
190 { GPU_ID2_VERSION_MAKE(0, 1, 1), base_hw_issues_tNAx_r0p1 },
191 { U32_MAX, NULL } } },
192
193 { GPU_ID2_PRODUCT_LBEX,
194 { { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_lBEx_r1p0 },
195 { GPU_ID2_VERSION_MAKE(1, 1, 0), base_hw_issues_lBEx_r1p1 },
196 { U32_MAX, NULL } } },
197
198 { GPU_ID2_PRODUCT_TBEX,
199 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tBEx_r0p0 },
200 { GPU_ID2_VERSION_MAKE(0, 0, 3), base_hw_issues_tBEx_r0p0 },
201 { GPU_ID2_VERSION_MAKE(0, 1, 0), base_hw_issues_tBEx_r0p1 },
202 { GPU_ID2_VERSION_MAKE(1, 0, 0), base_hw_issues_tBEx_r1p0 },
203 { U32_MAX, NULL } } },
204
205 { GPU_ID2_PRODUCT_TBAX,
206 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tBAx_r0p0 },
207 { GPU_ID2_VERSION_MAKE(0, 0, 1), base_hw_issues_tBAx_r0p0 },
208 { GPU_ID2_VERSION_MAKE(0, 0, 2), base_hw_issues_tBAx_r0p0 },
209 { U32_MAX, NULL } } },
210
211 { GPU_ID2_PRODUCT_TDUX,
212 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tDUx_r0p0 },
213 { U32_MAX, NULL } } },
214
215 { GPU_ID2_PRODUCT_TODX,
216 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tODx_r0p0 },
217 { GPU_ID2_VERSION_MAKE(0, 0, 4), base_hw_issues_tODx_r0p0 },
218 { GPU_ID2_VERSION_MAKE(0, 0, 5), base_hw_issues_tODx_r0p0 },
219 { U32_MAX, NULL } } },
220
221 { GPU_ID2_PRODUCT_LODX,
222 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tODx_r0p0 },
223 { U32_MAX, NULL } } },
224
225 { GPU_ID2_PRODUCT_TGRX,
226 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tGRx_r0p0 },
227 { U32_MAX, NULL } } },
228
229 { GPU_ID2_PRODUCT_TVAX,
230 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tVAx_r0p0 },
231 { U32_MAX, NULL } } },
232
233 { GPU_ID2_PRODUCT_TTUX,
234 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTUx_r0p0 },
235 { U32_MAX, NULL } } },
236
237 { GPU_ID2_PRODUCT_LTUX,
238 { { GPU_ID2_VERSION_MAKE(0, 0, 0), base_hw_issues_tTUx_r0p0 },
239 { U32_MAX, NULL } } },
240
241 };
242
243 u32 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id;
244 const u32 product_model = gpu_id & GPU_ID2_PRODUCT_MODEL;
245 const struct base_hw_product *product = NULL;
246 size_t p;
247
248 /* Stop when we reach the end of the products array. */
249 for (p = 0; p < ARRAY_SIZE(base_hw_products); ++p) {
250 if (product_model == base_hw_products[p].product_model) {
251 product = &base_hw_products[p];
252 break;
253 }
254 }
255
256 if (product != NULL) {
257 /* Found a matching product. */
258 const u32 version = gpu_id & GPU_ID2_VERSION;
259 u32 fallback_version = 0;
260 const enum base_hw_issue *fallback_issues = NULL;
261 size_t v;
262
263 /* Stop when we reach the end of the map. */
264 for (v = 0; product->map[v].version != U32_MAX; ++v) {
265
266 if (version == product->map[v].version) {
267 /* Exact match so stop. */
268 issues = product->map[v].issues;
269 break;
270 }
271
272 /* Check whether this is a candidate for most recent
273 * known version not later than the actual version.
274 */
275 if ((version > product->map[v].version) &&
276 (product->map[v].version >= fallback_version)) {
277 #if MALI_CUSTOMER_RELEASE
278 /* Match on version's major and minor fields */
279 if (((version ^ product->map[v].version) >>
280 GPU_ID2_VERSION_MINOR_SHIFT) == 0)
281 #endif
282 {
283 fallback_version = product->map[v].version;
284 fallback_issues = product->map[v].issues;
285 }
286 }
287 }
288
289 if ((issues == NULL) && (fallback_issues != NULL)) {
290 /* Fall back to the issue set of the most recent known
291 * version not later than the actual version.
292 */
293 issues = fallback_issues;
294
295 #if MALI_CUSTOMER_RELEASE
296 dev_warn(kbdev->dev,
297 "GPU hardware issue table may need updating:\n"
298 #else
299 dev_info(kbdev->dev,
300 #endif
301 "r%dp%d status %d is unknown; treating as r%dp%d status %d",
302 (gpu_id & GPU_ID2_VERSION_MAJOR) >>
303 GPU_ID2_VERSION_MAJOR_SHIFT,
304 (gpu_id & GPU_ID2_VERSION_MINOR) >>
305 GPU_ID2_VERSION_MINOR_SHIFT,
306 (gpu_id & GPU_ID2_VERSION_STATUS) >>
307 GPU_ID2_VERSION_STATUS_SHIFT,
308 (fallback_version & GPU_ID2_VERSION_MAJOR) >>
309 GPU_ID2_VERSION_MAJOR_SHIFT,
310 (fallback_version & GPU_ID2_VERSION_MINOR) >>
311 GPU_ID2_VERSION_MINOR_SHIFT,
312 (fallback_version & GPU_ID2_VERSION_STATUS) >>
313 GPU_ID2_VERSION_STATUS_SHIFT);
314
315 gpu_id &= ~GPU_ID2_VERSION;
316 gpu_id |= fallback_version;
317 kbdev->gpu_props.props.raw_props.gpu_id = gpu_id;
318
319 kbase_gpuprops_update_core_props_gpu_id(
320 &kbdev->gpu_props.props);
321 }
322 }
323 return issues;
324 }
325
kbase_hw_set_issues_mask(struct kbase_device * kbdev)326 int kbase_hw_set_issues_mask(struct kbase_device *kbdev)
327 {
328 const enum base_hw_issue *issues;
329 u32 gpu_id;
330 u32 impl_tech;
331
332 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id;
333 impl_tech = kbdev->gpu_props.props.thread_props.impl_tech;
334
335 if (impl_tech != IMPLEMENTATION_MODEL) {
336 issues = kbase_hw_get_issues_for_new_id(kbdev);
337 if (issues == NULL) {
338 dev_err(kbdev->dev,
339 "Unknown GPU ID %x", gpu_id);
340 return -EINVAL;
341 }
342
343 #if !MALI_CUSTOMER_RELEASE
344 /* The GPU ID might have been replaced with the last
345 * known version of the same GPU.
346 */
347 gpu_id = kbdev->gpu_props.props.raw_props.gpu_id;
348 #endif
349 } else {
350 /* Software model */
351 switch (gpu_id & GPU_ID2_PRODUCT_MODEL) {
352 case GPU_ID2_PRODUCT_TMIX:
353 issues = base_hw_issues_model_tMIx;
354 break;
355 case GPU_ID2_PRODUCT_THEX:
356 issues = base_hw_issues_model_tHEx;
357 break;
358 case GPU_ID2_PRODUCT_TSIX:
359 issues = base_hw_issues_model_tSIx;
360 break;
361 case GPU_ID2_PRODUCT_TDVX:
362 issues = base_hw_issues_model_tDVx;
363 break;
364 case GPU_ID2_PRODUCT_TNOX:
365 issues = base_hw_issues_model_tNOx;
366 break;
367 case GPU_ID2_PRODUCT_TGOX:
368 issues = base_hw_issues_model_tGOx;
369 break;
370 case GPU_ID2_PRODUCT_TTRX:
371 issues = base_hw_issues_model_tTRx;
372 break;
373 case GPU_ID2_PRODUCT_TNAX:
374 issues = base_hw_issues_model_tNAx;
375 break;
376 case GPU_ID2_PRODUCT_LBEX:
377 case GPU_ID2_PRODUCT_TBEX:
378 issues = base_hw_issues_model_tBEx;
379 break;
380 case GPU_ID2_PRODUCT_TBAX:
381 issues = base_hw_issues_model_tBAx;
382 break;
383 case GPU_ID2_PRODUCT_TDUX:
384 issues = base_hw_issues_model_tDUx;
385 break;
386 case GPU_ID2_PRODUCT_TODX:
387 case GPU_ID2_PRODUCT_LODX:
388 issues = base_hw_issues_model_tODx;
389 break;
390 case GPU_ID2_PRODUCT_TGRX:
391 issues = base_hw_issues_model_tGRx;
392 break;
393 case GPU_ID2_PRODUCT_TVAX:
394 issues = base_hw_issues_model_tVAx;
395 break;
396 case GPU_ID2_PRODUCT_TTUX:
397 case GPU_ID2_PRODUCT_LTUX:
398 issues = base_hw_issues_model_tTUx;
399 break;
400
401 default:
402 dev_err(kbdev->dev,
403 "Unknown GPU ID %x", gpu_id);
404 return -EINVAL;
405 }
406 }
407
408 dev_info(kbdev->dev,
409 "GPU identified as 0x%x arch %d.%d.%d r%dp%d status %d",
410 (gpu_id & GPU_ID2_PRODUCT_MAJOR) >>
411 GPU_ID2_PRODUCT_MAJOR_SHIFT,
412 (gpu_id & GPU_ID2_ARCH_MAJOR) >>
413 GPU_ID2_ARCH_MAJOR_SHIFT,
414 (gpu_id & GPU_ID2_ARCH_MINOR) >>
415 GPU_ID2_ARCH_MINOR_SHIFT,
416 (gpu_id & GPU_ID2_ARCH_REV) >>
417 GPU_ID2_ARCH_REV_SHIFT,
418 (gpu_id & GPU_ID2_VERSION_MAJOR) >>
419 GPU_ID2_VERSION_MAJOR_SHIFT,
420 (gpu_id & GPU_ID2_VERSION_MINOR) >>
421 GPU_ID2_VERSION_MINOR_SHIFT,
422 (gpu_id & GPU_ID2_VERSION_STATUS) >>
423 GPU_ID2_VERSION_STATUS_SHIFT);
424
425 for (; *issues != BASE_HW_ISSUE_END; issues++)
426 set_bit(*issues, &kbdev->hw_issues_mask[0]);
427
428 return 0;
429 }
430