1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2022 Intel Corporation
4 */
5
6 #include "xe_step.h"
7
8 #include <kunit/visibility.h>
9 #include <linux/bitfield.h>
10
11 #include "xe_device.h"
12 #include "xe_platform_types.h"
13
14 /*
15 * Provide mapping between PCI's revision ID to the individual GMD
16 * (Graphics/Media/Display) stepping values that can be compared numerically.
17 *
18 * Some platforms may have unusual ways of mapping PCI revision ID to GMD
19 * steppings. E.g., in some cases a higher PCI revision may translate to a
20 * lower stepping of the GT and/or display IP.
21 *
22 * Also note that some revisions/steppings may have been set aside as
23 * placeholders but never materialized in real hardware; in those cases there
24 * may be jumps in the revision IDs or stepping values in the tables below.
25 */
26
27 /*
28 * Some platforms always have the same stepping value for GT and display;
29 * use a macro to define these to make it easier to identify the platforms
30 * where the two steppings can deviate.
31 */
32 #define COMMON_STEP(x_) \
33 .graphics = STEP_##x_, \
34 .media = STEP_##x_
35
36 __diag_push();
37 __diag_ignore_all("-Woverride-init", "Allow field overrides in table");
38
39 /* Same GT stepping between tgl_uy_revids and tgl_revids don't mean the same HW */
40 static const struct xe_step_info tgl_revids[] = {
41 [0] = { COMMON_STEP(A0) },
42 [1] = { COMMON_STEP(B0) },
43 };
44
45 static const struct xe_step_info dg1_revids[] = {
46 [0] = { COMMON_STEP(A0) },
47 [1] = { COMMON_STEP(B0) },
48 };
49
50 static const struct xe_step_info adls_revids[] = {
51 [0x0] = { COMMON_STEP(A0) },
52 [0x1] = { COMMON_STEP(A0) },
53 [0x4] = { COMMON_STEP(B0) },
54 [0x8] = { COMMON_STEP(C0) },
55 [0xC] = { COMMON_STEP(D0) },
56 };
57
58 static const struct xe_step_info adls_rpls_revids[] = {
59 [0x4] = { COMMON_STEP(D0) },
60 [0xC] = { COMMON_STEP(D0) },
61 };
62
63 static const struct xe_step_info adlp_revids[] = {
64 [0x0] = { COMMON_STEP(A0) },
65 [0x4] = { COMMON_STEP(B0) },
66 [0x8] = { COMMON_STEP(C0) },
67 [0xC] = { COMMON_STEP(C0) },
68 };
69
70 static const struct xe_step_info adlp_rpl_revids[] = {
71 [0x4] = { COMMON_STEP(C0) },
72 };
73
74 static const struct xe_step_info adln_revids[] = {
75 [0x0] = { COMMON_STEP(A0) },
76 };
77
78 static const struct xe_step_info dg2_g10_revid_step_tbl[] = {
79 [0x0] = { COMMON_STEP(A0) },
80 [0x1] = { COMMON_STEP(A1) },
81 [0x4] = { COMMON_STEP(B0) },
82 [0x8] = { COMMON_STEP(C0) },
83 };
84
85 static const struct xe_step_info dg2_g11_revid_step_tbl[] = {
86 [0x0] = { COMMON_STEP(A0) },
87 [0x4] = { COMMON_STEP(B0) },
88 [0x5] = { COMMON_STEP(B1) },
89 };
90
91 static const struct xe_step_info dg2_g12_revid_step_tbl[] = {
92 [0x0] = { COMMON_STEP(A0) },
93 [0x1] = { COMMON_STEP(A1) },
94 };
95
96 static const struct xe_step_info pvc_revid_step_tbl[] = {
97 [0x5] = { .graphics = STEP_B0 },
98 [0x6] = { .graphics = STEP_B1 },
99 [0x7] = { .graphics = STEP_C0 },
100 };
101
102 static const int pvc_basedie_subids[] = {
103 [0x3] = STEP_B0,
104 [0x4] = STEP_B1,
105 [0x5] = STEP_B3,
106 };
107
108 __diag_pop();
109
110 /**
111 * xe_step_pre_gmdid_get - Determine IP steppings from PCI revid
112 * @xe: Xe device
113 *
114 * Convert the PCI revid into proper IP steppings. This should only be
115 * used on platforms that do not have GMD_ID support.
116 */
xe_step_pre_gmdid_get(struct xe_device * xe)117 struct xe_step_info xe_step_pre_gmdid_get(struct xe_device *xe)
118 {
119 const struct xe_step_info *revids = NULL;
120 struct xe_step_info step = {};
121 u16 revid = xe->info.revid;
122 int size = 0;
123 const int *basedie_info = NULL;
124 int basedie_size = 0;
125 int baseid = 0;
126
127 if (xe->info.platform == XE_PVC) {
128 baseid = FIELD_GET(GENMASK(5, 3), xe->info.revid);
129 revid = FIELD_GET(GENMASK(2, 0), xe->info.revid);
130 revids = pvc_revid_step_tbl;
131 size = ARRAY_SIZE(pvc_revid_step_tbl);
132 basedie_info = pvc_basedie_subids;
133 basedie_size = ARRAY_SIZE(pvc_basedie_subids);
134 } else if (xe->info.subplatform == XE_SUBPLATFORM_DG2_G10) {
135 revids = dg2_g10_revid_step_tbl;
136 size = ARRAY_SIZE(dg2_g10_revid_step_tbl);
137 } else if (xe->info.subplatform == XE_SUBPLATFORM_DG2_G11) {
138 revids = dg2_g11_revid_step_tbl;
139 size = ARRAY_SIZE(dg2_g11_revid_step_tbl);
140 } else if (xe->info.subplatform == XE_SUBPLATFORM_DG2_G12) {
141 revids = dg2_g12_revid_step_tbl;
142 size = ARRAY_SIZE(dg2_g12_revid_step_tbl);
143 } else if (xe->info.platform == XE_ALDERLAKE_N) {
144 revids = adln_revids;
145 size = ARRAY_SIZE(adln_revids);
146 } else if (xe->info.subplatform == XE_SUBPLATFORM_ALDERLAKE_S_RPLS) {
147 revids = adls_rpls_revids;
148 size = ARRAY_SIZE(adls_rpls_revids);
149 } else if (xe->info.subplatform == XE_SUBPLATFORM_ALDERLAKE_P_RPLU) {
150 revids = adlp_rpl_revids;
151 size = ARRAY_SIZE(adlp_rpl_revids);
152 } else if (xe->info.platform == XE_ALDERLAKE_P) {
153 revids = adlp_revids;
154 size = ARRAY_SIZE(adlp_revids);
155 } else if (xe->info.platform == XE_ALDERLAKE_S) {
156 revids = adls_revids;
157 size = ARRAY_SIZE(adls_revids);
158 } else if (xe->info.platform == XE_DG1) {
159 revids = dg1_revids;
160 size = ARRAY_SIZE(dg1_revids);
161 } else if (xe->info.platform == XE_TIGERLAKE) {
162 revids = tgl_revids;
163 size = ARRAY_SIZE(tgl_revids);
164 }
165
166 /* Not using the stepping scheme for the platform yet. */
167 if (!revids)
168 return step;
169
170 if (revid < size && revids[revid].graphics != STEP_NONE) {
171 step = revids[revid];
172 } else {
173 drm_warn(&xe->drm, "Unknown revid 0x%02x\n", revid);
174
175 /*
176 * If we hit a gap in the revid array, use the information for
177 * the next revid.
178 *
179 * This may be wrong in all sorts of ways, especially if the
180 * steppings in the array are not monotonically increasing, but
181 * it's better than defaulting to 0.
182 */
183 while (revid < size && revids[revid].graphics == STEP_NONE)
184 revid++;
185
186 if (revid < size) {
187 drm_dbg(&xe->drm, "Using steppings for revid 0x%02x\n",
188 revid);
189 step = revids[revid];
190 } else {
191 drm_dbg(&xe->drm, "Using future steppings\n");
192 step.graphics = STEP_FUTURE;
193 }
194 }
195
196 drm_WARN_ON(&xe->drm, step.graphics == STEP_NONE);
197
198 if (basedie_info && basedie_size) {
199 if (baseid < basedie_size && basedie_info[baseid] != STEP_NONE) {
200 step.basedie = basedie_info[baseid];
201 } else {
202 drm_warn(&xe->drm, "Unknown baseid 0x%02x\n", baseid);
203 step.basedie = STEP_FUTURE;
204 }
205 }
206
207 return step;
208 }
209
210 /**
211 * xe_step_gmdid_get - Determine IP steppings from GMD_ID revid fields
212 * @xe: Xe device
213 * @graphics_gmdid_revid: value of graphics GMD_ID register's revid field
214 * @media_gmdid_revid: value of media GMD_ID register's revid field
215 *
216 * Convert the revid fields of the GMD_ID registers into proper IP steppings.
217 *
218 * GMD_ID revid values are currently expected to have consistent meanings on
219 * all platforms: major steppings (A0, B0, etc.) are 4 apart, with minor
220 * steppings (A1, A2, etc.) taking the values in between.
221 */
xe_step_gmdid_get(struct xe_device * xe,u32 graphics_gmdid_revid,u32 media_gmdid_revid)222 struct xe_step_info xe_step_gmdid_get(struct xe_device *xe,
223 u32 graphics_gmdid_revid,
224 u32 media_gmdid_revid)
225 {
226 struct xe_step_info step = {
227 .graphics = STEP_A0 + graphics_gmdid_revid,
228 .media = STEP_A0 + media_gmdid_revid,
229 };
230
231 if (step.graphics >= STEP_FUTURE) {
232 step.graphics = STEP_FUTURE;
233 drm_dbg(&xe->drm, "Graphics GMD_ID revid value %d treated as future stepping\n",
234 graphics_gmdid_revid);
235 }
236
237 if (step.media >= STEP_FUTURE) {
238 step.media = STEP_FUTURE;
239 drm_dbg(&xe->drm, "Media GMD_ID revid value %d treated as future stepping\n",
240 media_gmdid_revid);
241 }
242
243 return step;
244 }
245
246 #define STEP_NAME_CASE(name) \
247 case STEP_##name: \
248 return #name;
249
xe_step_name(enum xe_step step)250 const char *xe_step_name(enum xe_step step)
251 {
252 switch (step) {
253 STEP_NAME_LIST(STEP_NAME_CASE);
254
255 default:
256 return "**";
257 }
258 }
259 EXPORT_SYMBOL_IF_KUNIT(xe_step_name);
260