Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/v3d: Associate a V3D tech revision to all supported devices

The V3D driver currently determines the GPU tech version (33, 41...)
by reading a register. This approach has worked so far since this
information wasn’t needed before powering on the GPU.

V3D 7.1 introduces new registers that must be written to power on the
GPU, requiring us to know the V3D version beforehand. To address this,
associate each supported SoC with the corresponding VideoCore GPU version
as part of the device data.

To prevent possible mistakes, add an assertion to verify that the version
specified in the device data matches the one reported by the hardware.
If there is a mismatch, the kernel will trigger a warning.

With the goal of maintaining consistency around the driver, use `enum
v3d_gen` to assign values to `v3d->ver` and for comparisons with other
V3D generations. Note that all mentions of unsupported or non-existing V3D
generations (such as V3D 4.0) were removed by this commit and replaced
with supported generations without functional changes.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Reviewed-by: Stefan Wahren <wahrenst@gmx.net>
Signed-off-by: Maíra Canal <mcanal@igalia.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250317-v3d-gpu-reset-fixes-v6-1-f3ee7717ed17@igalia.com

+96 -79
+58 -58
drivers/gpu/drm/v3d/v3d_debugfs.c
··· 21 21 }; 22 22 23 23 static const struct v3d_reg_def v3d_hub_reg_defs[] = { 24 - REGDEF(33, 42, V3D_HUB_AXICFG), 25 - REGDEF(33, 71, V3D_HUB_UIFCFG), 26 - REGDEF(33, 71, V3D_HUB_IDENT0), 27 - REGDEF(33, 71, V3D_HUB_IDENT1), 28 - REGDEF(33, 71, V3D_HUB_IDENT2), 29 - REGDEF(33, 71, V3D_HUB_IDENT3), 30 - REGDEF(33, 71, V3D_HUB_INT_STS), 31 - REGDEF(33, 71, V3D_HUB_INT_MSK_STS), 24 + REGDEF(V3D_GEN_33, V3D_GEN_42, V3D_HUB_AXICFG), 25 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_HUB_UIFCFG), 26 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_HUB_IDENT0), 27 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_HUB_IDENT1), 28 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_HUB_IDENT2), 29 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_HUB_IDENT3), 30 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_HUB_INT_STS), 31 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_HUB_INT_MSK_STS), 32 32 33 - REGDEF(33, 71, V3D_MMU_CTL), 34 - REGDEF(33, 71, V3D_MMU_VIO_ADDR), 35 - REGDEF(33, 71, V3D_MMU_VIO_ID), 36 - REGDEF(33, 71, V3D_MMU_DEBUG_INFO), 33 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_MMU_CTL), 34 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_MMU_VIO_ADDR), 35 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_MMU_VIO_ID), 36 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_MMU_DEBUG_INFO), 37 37 38 - REGDEF(71, 71, V3D_GMP_STATUS(71)), 39 - REGDEF(71, 71, V3D_GMP_CFG(71)), 40 - REGDEF(71, 71, V3D_GMP_VIO_ADDR(71)), 38 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_GMP_STATUS(71)), 39 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_GMP_CFG(71)), 40 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_GMP_VIO_ADDR(71)), 41 41 }; 42 42 43 43 static const struct v3d_reg_def v3d_gca_reg_defs[] = { 44 - REGDEF(33, 33, V3D_GCA_SAFE_SHUTDOWN), 45 - REGDEF(33, 33, V3D_GCA_SAFE_SHUTDOWN_ACK), 44 + REGDEF(V3D_GEN_33, V3D_GEN_33, V3D_GCA_SAFE_SHUTDOWN), 45 + REGDEF(V3D_GEN_33, V3D_GEN_33, V3D_GCA_SAFE_SHUTDOWN_ACK), 46 46 }; 47 47 48 48 static const struct v3d_reg_def v3d_core_reg_defs[] = { 49 - REGDEF(33, 71, V3D_CTL_IDENT0), 50 - REGDEF(33, 71, V3D_CTL_IDENT1), 51 - REGDEF(33, 71, V3D_CTL_IDENT2), 52 - REGDEF(33, 71, V3D_CTL_MISCCFG), 53 - REGDEF(33, 71, V3D_CTL_INT_STS), 54 - REGDEF(33, 71, V3D_CTL_INT_MSK_STS), 55 - REGDEF(33, 71, V3D_CLE_CT0CS), 56 - REGDEF(33, 71, V3D_CLE_CT0CA), 57 - REGDEF(33, 71, V3D_CLE_CT0EA), 58 - REGDEF(33, 71, V3D_CLE_CT1CS), 59 - REGDEF(33, 71, V3D_CLE_CT1CA), 60 - REGDEF(33, 71, V3D_CLE_CT1EA), 49 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CTL_IDENT0), 50 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CTL_IDENT1), 51 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CTL_IDENT2), 52 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CTL_MISCCFG), 53 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CTL_INT_STS), 54 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CTL_INT_MSK_STS), 55 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CLE_CT0CS), 56 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CLE_CT0CA), 57 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CLE_CT0EA), 58 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CLE_CT1CS), 59 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CLE_CT1CA), 60 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_CLE_CT1EA), 61 61 62 - REGDEF(33, 71, V3D_PTB_BPCA), 63 - REGDEF(33, 71, V3D_PTB_BPCS), 62 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_PTB_BPCA), 63 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_PTB_BPCS), 64 64 65 - REGDEF(33, 42, V3D_GMP_STATUS(33)), 66 - REGDEF(33, 42, V3D_GMP_CFG(33)), 67 - REGDEF(33, 42, V3D_GMP_VIO_ADDR(33)), 65 + REGDEF(V3D_GEN_33, V3D_GEN_42, V3D_GMP_STATUS(33)), 66 + REGDEF(V3D_GEN_33, V3D_GEN_42, V3D_GMP_CFG(33)), 67 + REGDEF(V3D_GEN_33, V3D_GEN_42, V3D_GMP_VIO_ADDR(33)), 68 68 69 - REGDEF(33, 71, V3D_ERR_FDBGO), 70 - REGDEF(33, 71, V3D_ERR_FDBGB), 71 - REGDEF(33, 71, V3D_ERR_FDBGS), 72 - REGDEF(33, 71, V3D_ERR_STAT), 69 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_ERR_FDBGO), 70 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_ERR_FDBGB), 71 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_ERR_FDBGS), 72 + REGDEF(V3D_GEN_33, V3D_GEN_71, V3D_ERR_STAT), 73 73 }; 74 74 75 75 static const struct v3d_reg_def v3d_csd_reg_defs[] = { 76 - REGDEF(41, 71, V3D_CSD_STATUS), 77 - REGDEF(41, 42, V3D_CSD_CURRENT_CFG0(41)), 78 - REGDEF(41, 42, V3D_CSD_CURRENT_CFG1(41)), 79 - REGDEF(41, 42, V3D_CSD_CURRENT_CFG2(41)), 80 - REGDEF(41, 42, V3D_CSD_CURRENT_CFG3(41)), 81 - REGDEF(41, 42, V3D_CSD_CURRENT_CFG4(41)), 82 - REGDEF(41, 42, V3D_CSD_CURRENT_CFG5(41)), 83 - REGDEF(41, 42, V3D_CSD_CURRENT_CFG6(41)), 84 - REGDEF(71, 71, V3D_CSD_CURRENT_CFG0(71)), 85 - REGDEF(71, 71, V3D_CSD_CURRENT_CFG1(71)), 86 - REGDEF(71, 71, V3D_CSD_CURRENT_CFG2(71)), 87 - REGDEF(71, 71, V3D_CSD_CURRENT_CFG3(71)), 88 - REGDEF(71, 71, V3D_CSD_CURRENT_CFG4(71)), 89 - REGDEF(71, 71, V3D_CSD_CURRENT_CFG5(71)), 90 - REGDEF(71, 71, V3D_CSD_CURRENT_CFG6(71)), 91 - REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG7), 76 + REGDEF(V3D_GEN_41, V3D_GEN_71, V3D_CSD_STATUS), 77 + REGDEF(V3D_GEN_41, V3D_GEN_42, V3D_CSD_CURRENT_CFG0(41)), 78 + REGDEF(V3D_GEN_41, V3D_GEN_42, V3D_CSD_CURRENT_CFG1(41)), 79 + REGDEF(V3D_GEN_41, V3D_GEN_42, V3D_CSD_CURRENT_CFG2(41)), 80 + REGDEF(V3D_GEN_41, V3D_GEN_42, V3D_CSD_CURRENT_CFG3(41)), 81 + REGDEF(V3D_GEN_41, V3D_GEN_42, V3D_CSD_CURRENT_CFG4(41)), 82 + REGDEF(V3D_GEN_41, V3D_GEN_42, V3D_CSD_CURRENT_CFG5(41)), 83 + REGDEF(V3D_GEN_41, V3D_GEN_42, V3D_CSD_CURRENT_CFG6(41)), 84 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_CSD_CURRENT_CFG0(71)), 85 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_CSD_CURRENT_CFG1(71)), 86 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_CSD_CURRENT_CFG2(71)), 87 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_CSD_CURRENT_CFG3(71)), 88 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_CSD_CURRENT_CFG4(71)), 89 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_CSD_CURRENT_CFG5(71)), 90 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_CSD_CURRENT_CFG6(71)), 91 + REGDEF(V3D_GEN_71, V3D_GEN_71, V3D_V7_CSD_CURRENT_CFG7), 92 92 }; 93 93 94 94 static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused) ··· 164 164 str_yes_no(ident2 & V3D_HUB_IDENT2_WITH_MMU)); 165 165 seq_printf(m, "TFU: %s\n", 166 166 str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TFU)); 167 - if (v3d->ver <= 42) { 167 + if (v3d->ver <= V3D_GEN_42) { 168 168 seq_printf(m, "TSY: %s\n", 169 169 str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TSY)); 170 170 } ··· 196 196 seq_printf(m, " QPUs: %d\n", nslc * qups); 197 197 seq_printf(m, " Semaphores: %d\n", 198 198 V3D_GET_FIELD(ident1, V3D_IDENT1_NSEM)); 199 - if (v3d->ver <= 42) { 199 + if (v3d->ver <= V3D_GEN_42) { 200 200 seq_printf(m, " BCG int: %d\n", 201 201 (ident2 & V3D_IDENT2_BCG_INT) != 0); 202 202 } 203 - if (v3d->ver < 40) { 203 + if (v3d->ver < V3D_GEN_41) { 204 204 seq_printf(m, " Override TMU: %d\n", 205 205 (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0); 206 206 } ··· 234 234 int core = 0; 235 235 int measure_ms = 1000; 236 236 237 - if (v3d->ver >= 40) { 237 + if (v3d->ver >= V3D_GEN_41) { 238 238 int cycle_count_reg = V3D_PCTR_CYCLE_COUNT(v3d->ver); 239 239 V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3, 240 240 V3D_SET_FIELD_VER(cycle_count_reg,
+16 -6
drivers/gpu/drm/v3d/v3d_drv.c
··· 17 17 #include <linux/dma-mapping.h> 18 18 #include <linux/io.h> 19 19 #include <linux/module.h> 20 + #include <linux/of.h> 20 21 #include <linux/of_platform.h> 21 22 #include <linux/platform_device.h> 22 23 #include <linux/sched/clock.h> ··· 93 92 args->value = 1; 94 93 return 0; 95 94 case DRM_V3D_PARAM_SUPPORTS_PERFMON: 96 - args->value = (v3d->ver >= 40); 95 + args->value = (v3d->ver >= V3D_GEN_41); 97 96 return 0; 98 97 case DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT: 99 98 args->value = 1; ··· 255 254 }; 256 255 257 256 static const struct of_device_id v3d_of_match[] = { 258 - { .compatible = "brcm,2711-v3d" }, 259 - { .compatible = "brcm,2712-v3d" }, 260 - { .compatible = "brcm,7268-v3d" }, 261 - { .compatible = "brcm,7278-v3d" }, 257 + { .compatible = "brcm,2711-v3d", .data = (void *)V3D_GEN_42 }, 258 + { .compatible = "brcm,2712-v3d", .data = (void *)V3D_GEN_71 }, 259 + { .compatible = "brcm,7268-v3d", .data = (void *)V3D_GEN_33 }, 260 + { .compatible = "brcm,7278-v3d", .data = (void *)V3D_GEN_41 }, 262 261 {}, 263 262 }; 264 263 MODULE_DEVICE_TABLE(of, v3d_of_match); ··· 275 274 struct device *dev = &pdev->dev; 276 275 struct drm_device *drm; 277 276 struct v3d_dev *v3d; 277 + enum v3d_gen gen; 278 278 int ret; 279 279 u32 mmu_debug; 280 280 u32 ident1, ident3; ··· 288 286 drm = &v3d->drm; 289 287 290 288 platform_set_drvdata(pdev, drm); 289 + 290 + gen = (uintptr_t)of_device_get_match_data(dev); 291 + v3d->ver = gen; 291 292 292 293 ret = map_regs(v3d, &v3d->hub_regs, "hub"); 293 294 if (ret) ··· 321 316 ident1 = V3D_READ(V3D_HUB_IDENT1); 322 317 v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 + 323 318 V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_REV)); 319 + /* Make sure that the V3D tech version retrieved from the HW is equal 320 + * to the one advertised by the device tree. 321 + */ 322 + WARN_ON(v3d->ver != gen); 323 + 324 324 v3d->cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES); 325 325 WARN_ON(v3d->cores > 1); /* multicore not yet implemented */ 326 326 ··· 350 340 } 351 341 } 352 342 353 - if (v3d->ver < 41) { 343 + if (v3d->ver < V3D_GEN_41) { 354 344 ret = map_regs(v3d, &v3d->gca_regs, "gca"); 355 345 if (ret) 356 346 goto clk_disable;
+9 -2
drivers/gpu/drm/v3d/v3d_drv.h
··· 94 94 u64 values[] __counted_by(ncounters); 95 95 }; 96 96 97 + enum v3d_gen { 98 + V3D_GEN_33 = 33, 99 + V3D_GEN_41 = 41, 100 + V3D_GEN_42 = 42, 101 + V3D_GEN_71 = 71, 102 + }; 103 + 97 104 struct v3d_dev { 98 105 struct drm_device drm; 99 106 100 107 /* Short representation (e.g. 33, 41) of the V3D tech version */ 101 - int ver; 108 + enum v3d_gen ver; 102 109 103 110 /* Short representation (e.g. 5, 6) of the V3D tech revision */ 104 111 int rev; ··· 206 199 static inline bool 207 200 v3d_has_csd(struct v3d_dev *v3d) 208 201 { 209 - return v3d->ver >= 41; 202 + return v3d->ver >= V3D_GEN_41; 210 203 } 211 204 212 205 #define v3d_to_pdev(v3d) to_platform_device((v3d)->drm.dev)
+5 -5
drivers/gpu/drm/v3d/v3d_gem.c
··· 25 25 * type. If you want the default behavior, you can still put 26 26 * "2" in the indirect texture state's output_type field. 27 27 */ 28 - if (v3d->ver < 40) 28 + if (v3d->ver < V3D_GEN_41) 29 29 V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT); 30 30 31 31 /* Whenever we flush the L2T cache, we always want to flush ··· 58 58 static void 59 59 v3d_idle_gca(struct v3d_dev *v3d) 60 60 { 61 - if (v3d->ver >= 41) 61 + if (v3d->ver >= V3D_GEN_41) 62 62 return; 63 63 64 64 V3D_GCA_WRITE(V3D_GCA_SAFE_SHUTDOWN, V3D_GCA_SAFE_SHUTDOWN_EN); ··· 132 132 static void 133 133 v3d_flush_l3(struct v3d_dev *v3d) 134 134 { 135 - if (v3d->ver < 41) { 135 + if (v3d->ver < V3D_GEN_41) { 136 136 u32 gca_ctrl = V3D_GCA_READ(V3D_GCA_CACHE_CTRL); 137 137 138 138 V3D_GCA_WRITE(V3D_GCA_CACHE_CTRL, 139 139 gca_ctrl | V3D_GCA_CACHE_CTRL_FLUSH); 140 140 141 - if (v3d->ver < 33) { 141 + if (v3d->ver < V3D_GEN_33) { 142 142 V3D_GCA_WRITE(V3D_GCA_CACHE_CTRL, 143 143 gca_ctrl & ~V3D_GCA_CACHE_CTRL_FLUSH); 144 144 } ··· 151 151 static void 152 152 v3d_invalidate_l2c(struct v3d_dev *v3d, int core) 153 153 { 154 - if (v3d->ver > 32) 154 + if (v3d->ver >= V3D_GEN_33) 155 155 return; 156 156 157 157 V3D_CORE_WRITE(core, V3D_CTL_L2CACTL,
+3 -3
drivers/gpu/drm/v3d/v3d_irq.c
··· 143 143 /* We shouldn't be triggering these if we have GMP in 144 144 * always-allowed mode. 145 145 */ 146 - if (v3d->ver < 71 && (intsts & V3D_INT_GMPV)) 146 + if (v3d->ver < V3D_GEN_71 && (intsts & V3D_INT_GMPV)) 147 147 dev_err(v3d->drm.dev, "GMP violation\n"); 148 148 149 149 /* V3D 4.2 wires the hub and core IRQs together, so if we & ··· 200 200 201 201 V3D_WRITE(V3D_MMU_CTL, V3D_READ(V3D_MMU_CTL)); 202 202 203 - if (v3d->ver >= 41) { 203 + if (v3d->ver >= V3D_GEN_41) { 204 204 axi_id = axi_id >> 5; 205 205 if (axi_id < ARRAY_SIZE(v3d41_axi_ids)) 206 206 client = v3d41_axi_ids[axi_id]; ··· 217 217 status = IRQ_HANDLED; 218 218 } 219 219 220 - if (v3d->ver >= 71 && (intsts & V3D_V7_HUB_INT_GMPV)) { 220 + if (v3d->ver >= V3D_GEN_71 && (intsts & V3D_V7_HUB_INT_GMPV)) { 221 221 dev_err(v3d->drm.dev, "GMP Violation\n"); 222 222 status = IRQ_HANDLED; 223 223 }
+2 -2
drivers/gpu/drm/v3d/v3d_perfmon.c
··· 200 200 const struct v3d_perf_counter_desc *counters = NULL; 201 201 unsigned int max = 0; 202 202 203 - if (v3d->ver >= 71) { 203 + if (v3d->ver >= V3D_GEN_71) { 204 204 counters = v3d_v71_performance_counters; 205 205 max = ARRAY_SIZE(v3d_v71_performance_counters); 206 - } else if (v3d->ver >= 42) { 206 + } else if (v3d->ver >= V3D_GEN_42) { 207 207 counters = v3d_v42_performance_counters; 208 208 max = ARRAY_SIZE(v3d_v42_performance_counters); 209 209 }
+3 -3
drivers/gpu/drm/v3d/v3d_sched.c
··· 345 345 V3D_WRITE(V3D_TFU_ICA(v3d->ver), job->args.ica); 346 346 V3D_WRITE(V3D_TFU_IUA(v3d->ver), job->args.iua); 347 347 V3D_WRITE(V3D_TFU_IOA(v3d->ver), job->args.ioa); 348 - if (v3d->ver >= 71) 348 + if (v3d->ver >= V3D_GEN_71) 349 349 V3D_WRITE(V3D_V7_TFU_IOC, job->args.v71.ioc); 350 350 V3D_WRITE(V3D_TFU_IOS(v3d->ver), job->args.ios); 351 351 V3D_WRITE(V3D_TFU_COEF0(v3d->ver), job->args.coef[0]); 352 - if (v3d->ver >= 71 || (job->args.coef[0] & V3D_TFU_COEF0_USECOEF)) { 352 + if (v3d->ver >= V3D_GEN_71 || (job->args.coef[0] & V3D_TFU_COEF0_USECOEF)) { 353 353 V3D_WRITE(V3D_TFU_COEF1(v3d->ver), job->args.coef[1]); 354 354 V3D_WRITE(V3D_TFU_COEF2(v3d->ver), job->args.coef[2]); 355 355 V3D_WRITE(V3D_TFU_COEF3(v3d->ver), job->args.coef[3]); ··· 395 395 * 396 396 * XXX: Set the CFG7 register 397 397 */ 398 - if (v3d->ver >= 71) 398 + if (v3d->ver >= V3D_GEN_71) 399 399 V3D_CORE_WRITE(0, V3D_V7_CSD_QUEUED_CFG7, 0); 400 400 401 401 /* CFG0 write kicks off the job. */