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

Configure Feed

Select the types of activity you want to include in your feed.

drm/v3d: Use V3D_SMS registers for power on/off and reset on V3D 7.x

In addition to the standard reset controller, V3D 7.x requires configuring
the V3D_SMS registers for proper power on/off and reset. Add the new
registers to `v3d_regs.h` and ensure they are properly configured during
device probing, removal, and reset.

This change fixes GPU reset issues on the Raspberry Pi 5 (BCM2712).
Without exposing these registers, a GPU reset causes the GPU to hang,
stopping any further job execution and freezing the desktop GUI. The same
issue occurs when unloading and loading the v3d driver.

Link: https://github.com/raspberrypi/linux/issues/6660
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Signed-off-by: Maíra Canal <mcanal@igalia.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250317-v3d-gpu-reset-fixes-v6-5-f3ee7717ed17@igalia.com

+94
+40
drivers/gpu/drm/v3d/v3d_drv.c
··· 263 263 }; 264 264 MODULE_DEVICE_TABLE(of, v3d_of_match); 265 265 266 + static void 267 + v3d_idle_sms(struct v3d_dev *v3d) 268 + { 269 + if (v3d->ver < V3D_GEN_71) 270 + return; 271 + 272 + V3D_SMS_WRITE(V3D_SMS_TEE_CS, V3D_SMS_CLEAR_POWER_OFF); 273 + 274 + if (wait_for((V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_TEE_CS), 275 + V3D_SMS_STATE) == V3D_SMS_IDLE), 100)) { 276 + DRM_ERROR("Failed to power up SMS\n"); 277 + } 278 + 279 + v3d_reset_sms(v3d); 280 + } 281 + 282 + static void 283 + v3d_power_off_sms(struct v3d_dev *v3d) 284 + { 285 + if (v3d->ver < V3D_GEN_71) 286 + return; 287 + 288 + V3D_SMS_WRITE(V3D_SMS_TEE_CS, V3D_SMS_POWER_OFF); 289 + 290 + if (wait_for((V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_TEE_CS), 291 + V3D_SMS_STATE) == V3D_SMS_POWER_OFF_STATE), 100)) { 292 + DRM_ERROR("Failed to power off SMS\n"); 293 + } 294 + } 295 + 266 296 static int 267 297 map_regs(struct v3d_dev *v3d, void __iomem **regs, const char *name) 268 298 { ··· 330 300 if (ret) 331 301 return ret; 332 302 303 + if (v3d->ver >= V3D_GEN_71) { 304 + ret = map_regs(v3d, &v3d->sms_regs, "sms"); 305 + if (ret) 306 + return ret; 307 + } 308 + 333 309 v3d->clk = devm_clk_get_optional(dev, NULL); 334 310 if (IS_ERR(v3d->clk)) 335 311 return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n"); ··· 345 309 dev_err(&pdev->dev, "Couldn't enable the V3D clock\n"); 346 310 return ret; 347 311 } 312 + 313 + v3d_idle_sms(v3d); 348 314 349 315 mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO); 350 316 mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)); ··· 447 409 448 410 dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch, 449 411 v3d->mmu_scratch_paddr); 412 + 413 + v3d_power_off_sms(v3d); 450 414 451 415 clk_disable_unprepare(v3d->clk); 452 416 }
+11
drivers/gpu/drm/v3d/v3d_drv.h
··· 118 118 void __iomem *core_regs[3]; 119 119 void __iomem *bridge_regs; 120 120 void __iomem *gca_regs; 121 + void __iomem *sms_regs; 121 122 struct clk *clk; 122 123 struct reset_control *reset; 123 124 ··· 268 267 269 268 #define V3D_GCA_READ(offset) readl(v3d->gca_regs + offset) 270 269 #define V3D_GCA_WRITE(offset, val) writel(val, v3d->gca_regs + offset) 270 + 271 + #define V3D_SMS_IDLE 0x0 272 + #define V3D_SMS_ISOLATING_FOR_RESET 0xa 273 + #define V3D_SMS_RESETTING 0xb 274 + #define V3D_SMS_ISOLATING_FOR_POWER_OFF 0xc 275 + #define V3D_SMS_POWER_OFF_STATE 0xd 276 + 277 + #define V3D_SMS_READ(offset) readl(v3d->sms_regs + (offset)) 278 + #define V3D_SMS_WRITE(offset, val) writel(val, v3d->sms_regs + (offset)) 271 279 272 280 #define V3D_CORE_READ(core, offset) readl(v3d->core_regs[core] + offset) 273 281 #define V3D_CORE_WRITE(core, offset, val) writel(val, v3d->core_regs[core] + offset) ··· 556 546 /* v3d_gem.c */ 557 547 int v3d_gem_init(struct drm_device *dev); 558 548 void v3d_gem_destroy(struct drm_device *dev); 549 + void v3d_reset_sms(struct v3d_dev *v3d); 559 550 void v3d_reset(struct v3d_dev *v3d); 560 551 void v3d_invalidate_caches(struct v3d_dev *v3d); 561 552 void v3d_clean_caches(struct v3d_dev *v3d);
+17
drivers/gpu/drm/v3d/v3d_gem.c
··· 105 105 } 106 106 107 107 void 108 + v3d_reset_sms(struct v3d_dev *v3d) 109 + { 110 + if (v3d->ver < V3D_GEN_71) 111 + return; 112 + 113 + V3D_SMS_WRITE(V3D_SMS_REE_CS, V3D_SET_FIELD(0x4, V3D_SMS_STATE)); 114 + 115 + if (wait_for(!(V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_REE_CS), 116 + V3D_SMS_STATE) == V3D_SMS_ISOLATING_FOR_RESET) && 117 + !(V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_REE_CS), 118 + V3D_SMS_STATE) == V3D_SMS_RESETTING), 100)) { 119 + DRM_ERROR("Failed to wait for SMS reset\n"); 120 + } 121 + } 122 + 123 + void 108 124 v3d_reset(struct v3d_dev *v3d) 109 125 { 110 126 struct drm_device *dev = &v3d->drm; ··· 135 119 v3d_idle_axi(v3d, 0); 136 120 137 121 v3d_idle_gca(v3d); 122 + v3d_reset_sms(v3d); 138 123 v3d_reset_v3d(v3d); 139 124 140 125 v3d_mmu_set_page_table(v3d);
+26
drivers/gpu/drm/v3d/v3d_regs.h
··· 515 515 # define V3D_ERR_VPAERGS BIT(1) 516 516 # define V3D_ERR_VPAEABB BIT(0) 517 517 518 + #define V3D_SMS_REE_CS 0x00000 519 + #define V3D_SMS_TEE_CS 0x00400 520 + # define V3D_SMS_INTERRUPT BIT(31) 521 + # define V3D_SMS_POWER_OFF BIT(30) 522 + # define V3D_SMS_CLEAR_POWER_OFF BIT(29) 523 + # define V3D_SMS_LOCK BIT(28) 524 + # define V3D_SMS_CLEAR_LOCK BIT(27) 525 + # define V3D_SMS_SVP_MODE_EXIT BIT(26) 526 + # define V3D_SMS_CLEAR_SVP_MODE_EXIT BIT(25) 527 + # define V3D_SMS_SVP_MODE_ENTER BIT(24) 528 + # define V3D_SMS_CLEAR_SVP_MODE_ENTER BIT(23) 529 + # define V3D_SMS_THEIR_MODE_EXIT BIT(22) 530 + # define V3D_SMS_THEIR_MODE_ENTER BIT(21) 531 + # define V3D_SMS_OUR_MODE_EXIT BIT(20) 532 + # define V3D_SMS_CLEAR_OUR_MODE_EXIT BIT(19) 533 + # define V3D_SMS_SEQ_PC_MASK V3D_MASK(16, 10) 534 + # define V3D_SMS_SEQ_PC_SHIFT 10 535 + # define V3D_SMS_HUBCORE_STATUS_MASK V3D_MASK(9, 8) 536 + # define V3D_SMS_HUBCORE_STATUS_SHIFT 8 537 + # define V3D_SMS_NEW_MODE_MASK V3D_MASK(7, 6) 538 + # define V3D_SMS_NEW_MODE_SHIFT 6 539 + # define V3D_SMS_OLD_MODE_MASK V3D_MASK(5, 4) 540 + # define V3D_SMS_OLD_MODE_SHIFT 4 541 + # define V3D_SMS_STATE_MASK V3D_MASK(3, 0) 542 + # define V3D_SMS_STATE_SHIFT 0 543 + 518 544 #endif /* V3D_REGS_H */