]> git.ipfire.org Git - thirdparty/openwrt.git/blob
813c47c9fd5308320cb4f99a56e164081d70890c
[thirdparty/openwrt.git] /
1 From 850bf1a716c51db46a7e2ff4bf7e2968c22ab4bf Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= <mcanal@igalia.com>
3 Date: Tue, 11 Mar 2025 15:13:48 -0300
4 Subject: [PATCH] drm/v3d: Use V3D_SMS registers for power on/off and reset on
5 V3D 7.x
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 In addition to the standard reset controller, V3D 7.x requires configuring
11 the V3D_SMS registers for proper power on/off and reset. Add the new
12 registers to `v3d_regs.h` and ensure they are properly configured during
13 device probing, removal, and reset.
14
15 This change fixes GPU reset issues on the Raspberry Pi 5 (BCM2712).
16 Without exposing these registers, a GPU reset causes the GPU to hang,
17 stopping any further job execution and freezing the desktop GUI. The same
18 issue occurs when unloading and loading the v3d driver.
19
20 Link: https://github.com/raspberrypi/linux/issues/6660
21 Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
22 Signed-off-by: MaĆ­ra Canal <mcanal@igalia.com>
23 ---
24 drivers/gpu/drm/v3d/v3d_drv.c | 2 ++
25 drivers/gpu/drm/v3d/v3d_drv.h | 11 +++++++++++
26 drivers/gpu/drm/v3d/v3d_gem.c | 17 +++++++++++++++++
27 drivers/gpu/drm/v3d/v3d_regs.h | 26 ++++++++++++++++++++++++++
28 4 files changed, 56 insertions(+)
29
30 --- a/drivers/gpu/drm/v3d/v3d_drv.c
31 +++ b/drivers/gpu/drm/v3d/v3d_drv.c
32 @@ -485,6 +485,8 @@ static void v3d_platform_drm_remove(stru
33 dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch,
34 v3d->mmu_scratch_paddr);
35
36 + v3d_power_off_sms(v3d);
37 +
38 clk_disable_unprepare(v3d->clk);
39 }
40
41 --- a/drivers/gpu/drm/v3d/v3d_drv.h
42 +++ b/drivers/gpu/drm/v3d/v3d_drv.h
43 @@ -118,6 +118,7 @@ struct v3d_dev {
44 void __iomem *core_regs[3];
45 void __iomem *bridge_regs;
46 void __iomem *gca_regs;
47 + void __iomem *sms_regs;
48 struct clk *clk;
49 struct delayed_work clk_down_work;
50 unsigned long clk_up_rate, clk_down_rate;
51 @@ -274,6 +275,15 @@ to_v3d_fence(struct dma_fence *fence)
52 #define V3D_GCA_READ(offset) readl(v3d->gca_regs + offset)
53 #define V3D_GCA_WRITE(offset, val) writel(val, v3d->gca_regs + offset)
54
55 +#define V3D_SMS_IDLE 0x0
56 +#define V3D_SMS_ISOLATING_FOR_RESET 0xa
57 +#define V3D_SMS_RESETTING 0xb
58 +#define V3D_SMS_ISOLATING_FOR_POWER_OFF 0xc
59 +#define V3D_SMS_POWER_OFF_STATE 0xd
60 +
61 +#define V3D_SMS_READ(offset) readl(v3d->sms_regs + (offset))
62 +#define V3D_SMS_WRITE(offset, val) writel(val, v3d->sms_regs + (offset))
63 +
64 #define V3D_CORE_READ(core, offset) readl(v3d->core_regs[core] + offset)
65 #define V3D_CORE_WRITE(core, offset, val) writel(val, v3d->core_regs[core] + offset)
66
67 @@ -552,6 +562,7 @@ struct dma_fence *v3d_fence_create(struc
68 /* v3d_gem.c */
69 int v3d_gem_init(struct drm_device *dev);
70 void v3d_gem_destroy(struct drm_device *dev);
71 +void v3d_reset_sms(struct v3d_dev *v3d);
72 void v3d_reset(struct v3d_dev *v3d);
73 void v3d_invalidate_caches(struct v3d_dev *v3d);
74 void v3d_clean_caches(struct v3d_dev *v3d);
75 --- a/drivers/gpu/drm/v3d/v3d_gem.c
76 +++ b/drivers/gpu/drm/v3d/v3d_gem.c
77 @@ -106,6 +106,22 @@ v3d_reset_v3d(struct v3d_dev *v3d)
78 }
79
80 void
81 +v3d_reset_sms(struct v3d_dev *v3d)
82 +{
83 + if (v3d->ver < V3D_GEN_71)
84 + return;
85 +
86 + V3D_SMS_WRITE(V3D_SMS_REE_CS, V3D_SET_FIELD(0x4, V3D_SMS_STATE));
87 +
88 + if (wait_for(!(V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_REE_CS),
89 + V3D_SMS_STATE) == V3D_SMS_ISOLATING_FOR_RESET) &&
90 + !(V3D_GET_FIELD(V3D_SMS_READ(V3D_SMS_REE_CS),
91 + V3D_SMS_STATE) == V3D_SMS_RESETTING), 100)) {
92 + DRM_ERROR("Failed to wait for SMS reset\n");
93 + }
94 +}
95 +
96 +void
97 v3d_reset(struct v3d_dev *v3d)
98 {
99 struct drm_device *dev = &v3d->drm;
100 @@ -120,6 +136,7 @@ v3d_reset(struct v3d_dev *v3d)
101 v3d_idle_axi(v3d, 0);
102
103 v3d_idle_gca(v3d);
104 + v3d_reset_sms(v3d);
105 v3d_reset_v3d(v3d);
106
107 v3d_mmu_set_page_table(v3d);
108 --- a/drivers/gpu/drm/v3d/v3d_regs.h
109 +++ b/drivers/gpu/drm/v3d/v3d_regs.h
110 @@ -515,4 +515,30 @@
111 # define V3D_ERR_VPAERGS BIT(1)
112 # define V3D_ERR_VPAEABB BIT(0)
113
114 +#define V3D_SMS_REE_CS 0x00000
115 +#define V3D_SMS_TEE_CS 0x00400
116 +# define V3D_SMS_INTERRUPT BIT(31)
117 +# define V3D_SMS_POWER_OFF BIT(30)
118 +# define V3D_SMS_CLEAR_POWER_OFF BIT(29)
119 +# define V3D_SMS_LOCK BIT(28)
120 +# define V3D_SMS_CLEAR_LOCK BIT(27)
121 +# define V3D_SMS_SVP_MODE_EXIT BIT(26)
122 +# define V3D_SMS_CLEAR_SVP_MODE_EXIT BIT(25)
123 +# define V3D_SMS_SVP_MODE_ENTER BIT(24)
124 +# define V3D_SMS_CLEAR_SVP_MODE_ENTER BIT(23)
125 +# define V3D_SMS_THEIR_MODE_EXIT BIT(22)
126 +# define V3D_SMS_THEIR_MODE_ENTER BIT(21)
127 +# define V3D_SMS_OUR_MODE_EXIT BIT(20)
128 +# define V3D_SMS_CLEAR_OUR_MODE_EXIT BIT(19)
129 +# define V3D_SMS_SEQ_PC_MASK V3D_MASK(16, 10)
130 +# define V3D_SMS_SEQ_PC_SHIFT 10
131 +# define V3D_SMS_HUBCORE_STATUS_MASK V3D_MASK(9, 8)
132 +# define V3D_SMS_HUBCORE_STATUS_SHIFT 8
133 +# define V3D_SMS_NEW_MODE_MASK V3D_MASK(7, 6)
134 +# define V3D_SMS_NEW_MODE_SHIFT 6
135 +# define V3D_SMS_OLD_MODE_MASK V3D_MASK(5, 4)
136 +# define V3D_SMS_OLD_MODE_SHIFT 4
137 +# define V3D_SMS_STATE_MASK V3D_MASK(3, 0)
138 +# define V3D_SMS_STATE_SHIFT 0
139 +
140 #endif /* V3D_REGS_H */