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