Skip to content

Commit 85e1a75

Browse files
mairacanalpelwell
authored andcommitted
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: #6660 Signed-off-by: Maíra Canal <[email protected]>
1 parent 08e99bc commit 85e1a75

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

drivers/gpu/drm/v3d/v3d_drv.c

+40
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,36 @@ static const struct of_device_id v3d_of_match[] = {
198198
};
199199
MODULE_DEVICE_TABLE(of, v3d_of_match);
200200

201+
static void
202+
v3d_idle_sms(struct v3d_dev *v3d)
203+
{
204+
if (v3d->ver < V3D_GEN_71)
205+
return;
206+
207+
V3D_SMS_WRITE(V3D_SMS_TEE_CS, V3D_SMS_CLEAR_POWER_OFF);
208+
209+
if (wait_for((V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_TEE_CS),
210+
V3D_SMS_STATE) == V3D_SMS_IDLE), 100)) {
211+
DRM_ERROR("Failed to power up SMS\n");
212+
}
213+
214+
v3d_reset_sms(v3d);
215+
}
216+
217+
static void
218+
v3d_power_off_sms(struct v3d_dev *v3d)
219+
{
220+
if (v3d->ver < V3D_GEN_71)
221+
return;
222+
223+
V3D_SMS_WRITE(V3D_SMS_TEE_CS, V3D_SMS_POWER_OFF);
224+
225+
if (wait_for((V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_TEE_CS),
226+
V3D_SMS_STATE) == V3D_SMS_POWER_OFF_STATE), 100)) {
227+
DRM_ERROR("Failed to power off SMS\n");
228+
}
229+
}
230+
201231
static int
202232
map_regs(struct v3d_dev *v3d, void __iomem **regs, const char *name)
203233
{
@@ -237,6 +267,12 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
237267
if (ret)
238268
return ret;
239269

270+
if (v3d->ver >= V3D_GEN_71) {
271+
ret = map_regs(v3d, &v3d->sms_regs, "sms");
272+
if (ret)
273+
return ret;
274+
}
275+
240276
v3d->clk = devm_clk_get_optional(dev, NULL);
241277
if (IS_ERR(v3d->clk))
242278
return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n");
@@ -247,6 +283,8 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
247283
return ret;
248284
}
249285

286+
v3d_idle_sms(v3d);
287+
250288
mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
251289
mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
252290
ret = dma_set_mask_and_coherent(dev, mask);
@@ -361,6 +399,8 @@ static void v3d_platform_drm_remove(struct platform_device *pdev)
361399
dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch,
362400
v3d->mmu_scratch_paddr);
363401

402+
v3d_power_off_sms(v3d);
403+
364404
clk_disable_unprepare(v3d->clk);
365405
}
366406

drivers/gpu/drm/v3d/v3d_drv.h

+11
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ struct v3d_dev {
135135
void __iomem *core_regs[3];
136136
void __iomem *bridge_regs;
137137
void __iomem *gca_regs;
138+
void __iomem *sms_regs;
138139
struct clk *clk;
139140
struct delayed_work clk_down_work;
140141
unsigned long clk_up_rate, clk_down_rate;
@@ -277,6 +278,15 @@ to_v3d_fence(struct dma_fence *fence)
277278
#define V3D_GCA_READ(offset) readl(v3d->gca_regs + offset)
278279
#define V3D_GCA_WRITE(offset, val) writel(val, v3d->gca_regs + offset)
279280

281+
#define V3D_SMS_IDLE 0x0
282+
#define V3D_SMS_ISOLATING_FOR_RESET 0xa
283+
#define V3D_SMS_RESETTING 0xb
284+
#define V3D_SMS_ISOLATING_FOR_POWER_OFF 0xc
285+
#define V3D_SMS_POWER_OFF_STATE 0xd
286+
287+
#define V3D_SMS_READ(offset) readl(v3d->sms_regs + (offset))
288+
#define V3D_SMS_WRITE(offset, val) writel(val, v3d->sms_regs + (offset))
289+
280290
#define V3D_CORE_READ(core, offset) readl(v3d->core_regs[core] + offset)
281291
#define V3D_CORE_WRITE(core, offset, val) writel(val, v3d->core_regs[core] + offset)
282292

@@ -455,6 +465,7 @@ int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
455465
struct drm_file *file_priv);
456466
void v3d_job_cleanup(struct v3d_job *job);
457467
void v3d_job_put(struct v3d_job *job);
468+
void v3d_reset_sms(struct v3d_dev *v3d);
458469
void v3d_reset(struct v3d_dev *v3d);
459470
void v3d_invalidate_caches(struct v3d_dev *v3d);
460471
void v3d_clean_caches(struct v3d_dev *v3d);

drivers/gpu/drm/v3d/v3d_gem.c

+17
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,22 @@ v3d_reset_v3d(struct v3d_dev *v3d)
151151
v3d_init_hw_state(v3d);
152152
}
153153

154+
void
155+
v3d_reset_sms(struct v3d_dev *v3d)
156+
{
157+
if (v3d->ver < V3D_GEN_71)
158+
return;
159+
160+
V3D_SMS_WRITE(V3D_SMS_REE_CS, V3D_SET_FIELD(0x4, V3D_SMS_STATE));
161+
162+
if (wait_for(!(V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_REE_CS),
163+
V3D_SMS_STATE) == V3D_SMS_ISOLATING_FOR_RESET) &&
164+
!(V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_REE_CS),
165+
V3D_SMS_STATE) == V3D_SMS_RESETTING), 100)) {
166+
DRM_ERROR("Failed to wait for SMS reset\n");
167+
}
168+
}
169+
154170
void
155171
v3d_reset(struct v3d_dev *v3d)
156172
{
@@ -166,6 +182,7 @@ v3d_reset(struct v3d_dev *v3d)
166182
v3d_idle_axi(v3d, 0);
167183

168184
v3d_idle_gca(v3d);
185+
v3d_reset_sms(v3d);
169186
v3d_reset_v3d(v3d);
170187

171188
v3d_mmu_set_page_table(v3d);

drivers/gpu/drm/v3d/v3d_regs.h

+26
Original file line numberDiff line numberDiff line change
@@ -543,4 +543,30 @@
543543
# define V3D_ERR_VPAERGS BIT(1)
544544
# define V3D_ERR_VPAEABB BIT(0)
545545

546+
#define V3D_SMS_REE_CS 0x00000
547+
#define V3D_SMS_TEE_CS 0x00400
548+
# define V3D_SMS_INTERRUPT BIT(31)
549+
# define V3D_SMS_POWER_OFF BIT(30)
550+
# define V3D_SMS_CLEAR_POWER_OFF BIT(29)
551+
# define V3D_SMS_LOCK BIT(28)
552+
# define V3D_SMS_CLEAR_LOCK BIT(27)
553+
# define V3D_SMS_SVP_MODE_EXIT BIT(26)
554+
# define V3D_SMS_CLEAR_SVP_MODE_EXIT BIT(25)
555+
# define V3D_SMS_SVP_MODE_ENTER BIT(24)
556+
# define V3D_SMS_CLEAR_SVP_MODE_ENTER BIT(23)
557+
# define V3D_SMS_THEIR_MODE_EXIT BIT(22)
558+
# define V3D_SMS_THEIR_MODE_ENTER BIT(21)
559+
# define V3D_SMS_OUR_MODE_EXIT BIT(20)
560+
# define V3D_SMS_CLEAR_OUR_MODE_EXIT BIT(19)
561+
# define V3D_SMS_SEQ_PC_MASK V3D_MASK(16, 10)
562+
# define V3D_SMS_SEQ_PC_SHIFT 10
563+
# define V3D_SMS_HUBCORE_STATUS_MASK V3D_MASK(9, 8)
564+
# define V3D_SMS_HUBCORE_STATUS_SHIFT 8
565+
# define V3D_SMS_NEW_MODE_MASK V3D_MASK(7, 6)
566+
# define V3D_SMS_NEW_MODE_SHIFT 6
567+
# define V3D_SMS_OLD_MODE_MASK V3D_MASK(5, 4)
568+
# define V3D_SMS_OLD_MODE_SHIFT 4
569+
# define V3D_SMS_STATE_MASK V3D_MASK(3, 0)
570+
# define V3D_SMS_STATE_SHIFT 0
571+
546572
#endif /* V3D_REGS_H */

0 commit comments

Comments
 (0)