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