1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (c) 2015 MediaTek Inc.
4 */
5
6 #include <linux/clk.h>
7 #include <linux/iopoll.h>
8 #include <linux/module.h>
9 #include <linux/of_device.h>
10 #include <linux/platform_device.h>
11 #include <linux/regmap.h>
12 #include <linux/soc/mediatek/mtk-mmsys.h>
13 #include <linux/soc/mediatek/mtk-mutex.h>
14
15 #define MT2701_MUTEX0_MOD0 0x2c
16 #define MT2701_MUTEX0_SOF0 0x30
17 #define MT8183_MUTEX0_MOD0 0x30
18 #define MT8183_MUTEX0_SOF0 0x2c
19
20 #define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
21 #define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
22 #define DISP_REG_MUTEX_RST(n) (0x28 + 0x20 * (n))
23 #define DISP_REG_MUTEX_MOD(mutex_mod_reg, n) (mutex_mod_reg + 0x20 * (n))
24 #define DISP_REG_MUTEX_SOF(mutex_sof_reg, n) (mutex_sof_reg + 0x20 * (n))
25 #define DISP_REG_MUTEX_MOD2(n) (0x34 + 0x20 * (n))
26
27 #define INT_MUTEX BIT(1)
28
29 #define MT8186_MUTEX_MOD_DISP_OVL0 0
30 #define MT8186_MUTEX_MOD_DISP_OVL0_2L 1
31 #define MT8186_MUTEX_MOD_DISP_RDMA0 2
32 #define MT8186_MUTEX_MOD_DISP_COLOR0 4
33 #define MT8186_MUTEX_MOD_DISP_CCORR0 5
34 #define MT8186_MUTEX_MOD_DISP_AAL0 7
35 #define MT8186_MUTEX_MOD_DISP_GAMMA0 8
36 #define MT8186_MUTEX_MOD_DISP_POSTMASK0 9
37 #define MT8186_MUTEX_MOD_DISP_DITHER0 10
38 #define MT8186_MUTEX_MOD_DISP_RDMA1 17
39
40 #define MT8186_MUTEX_SOF_SINGLE_MODE 0
41 #define MT8186_MUTEX_SOF_DSI0 1
42 #define MT8186_MUTEX_SOF_DPI0 2
43 #define MT8186_MUTEX_EOF_DSI0 (MT8186_MUTEX_SOF_DSI0 << 6)
44 #define MT8186_MUTEX_EOF_DPI0 (MT8186_MUTEX_SOF_DPI0 << 6)
45
46 #define MT8167_MUTEX_MOD_DISP_PWM 1
47 #define MT8167_MUTEX_MOD_DISP_OVL0 6
48 #define MT8167_MUTEX_MOD_DISP_OVL1 7
49 #define MT8167_MUTEX_MOD_DISP_RDMA0 8
50 #define MT8167_MUTEX_MOD_DISP_RDMA1 9
51 #define MT8167_MUTEX_MOD_DISP_WDMA0 10
52 #define MT8167_MUTEX_MOD_DISP_CCORR 11
53 #define MT8167_MUTEX_MOD_DISP_COLOR 12
54 #define MT8167_MUTEX_MOD_DISP_AAL 13
55 #define MT8167_MUTEX_MOD_DISP_GAMMA 14
56 #define MT8167_MUTEX_MOD_DISP_DITHER 15
57 #define MT8167_MUTEX_MOD_DISP_UFOE 16
58
59 #define MT8192_MUTEX_MOD_DISP_OVL0 0
60 #define MT8192_MUTEX_MOD_DISP_OVL0_2L 1
61 #define MT8192_MUTEX_MOD_DISP_RDMA0 2
62 #define MT8192_MUTEX_MOD_DISP_COLOR0 4
63 #define MT8192_MUTEX_MOD_DISP_CCORR0 5
64 #define MT8192_MUTEX_MOD_DISP_AAL0 6
65 #define MT8192_MUTEX_MOD_DISP_GAMMA0 7
66 #define MT8192_MUTEX_MOD_DISP_POSTMASK0 8
67 #define MT8192_MUTEX_MOD_DISP_DITHER0 9
68 #define MT8192_MUTEX_MOD_DISP_OVL2_2L 16
69 #define MT8192_MUTEX_MOD_DISP_RDMA4 17
70
71 #define MT8183_MUTEX_MOD_DISP_RDMA0 0
72 #define MT8183_MUTEX_MOD_DISP_RDMA1 1
73 #define MT8183_MUTEX_MOD_DISP_OVL0 9
74 #define MT8183_MUTEX_MOD_DISP_OVL0_2L 10
75 #define MT8183_MUTEX_MOD_DISP_OVL1_2L 11
76 #define MT8183_MUTEX_MOD_DISP_WDMA0 12
77 #define MT8183_MUTEX_MOD_DISP_COLOR0 13
78 #define MT8183_MUTEX_MOD_DISP_CCORR0 14
79 #define MT8183_MUTEX_MOD_DISP_AAL0 15
80 #define MT8183_MUTEX_MOD_DISP_GAMMA0 16
81 #define MT8183_MUTEX_MOD_DISP_DITHER0 17
82
83 #define MT8173_MUTEX_MOD_DISP_OVL0 11
84 #define MT8173_MUTEX_MOD_DISP_OVL1 12
85 #define MT8173_MUTEX_MOD_DISP_RDMA0 13
86 #define MT8173_MUTEX_MOD_DISP_RDMA1 14
87 #define MT8173_MUTEX_MOD_DISP_RDMA2 15
88 #define MT8173_MUTEX_MOD_DISP_WDMA0 16
89 #define MT8173_MUTEX_MOD_DISP_WDMA1 17
90 #define MT8173_MUTEX_MOD_DISP_COLOR0 18
91 #define MT8173_MUTEX_MOD_DISP_COLOR1 19
92 #define MT8173_MUTEX_MOD_DISP_AAL 20
93 #define MT8173_MUTEX_MOD_DISP_GAMMA 21
94 #define MT8173_MUTEX_MOD_DISP_UFOE 22
95 #define MT8173_MUTEX_MOD_DISP_PWM0 23
96 #define MT8173_MUTEX_MOD_DISP_PWM1 24
97 #define MT8173_MUTEX_MOD_DISP_OD 25
98
99 #define MT8195_MUTEX_MOD_DISP_OVL0 0
100 #define MT8195_MUTEX_MOD_DISP_WDMA0 1
101 #define MT8195_MUTEX_MOD_DISP_RDMA0 2
102 #define MT8195_MUTEX_MOD_DISP_COLOR0 3
103 #define MT8195_MUTEX_MOD_DISP_CCORR0 4
104 #define MT8195_MUTEX_MOD_DISP_AAL0 5
105 #define MT8195_MUTEX_MOD_DISP_GAMMA0 6
106 #define MT8195_MUTEX_MOD_DISP_DITHER0 7
107 #define MT8195_MUTEX_MOD_DISP_DSI0 8
108 #define MT8195_MUTEX_MOD_DISP_DSC_WRAP0_CORE0 9
109 #define MT8195_MUTEX_MOD_DISP_VPP_MERGE 20
110 #define MT8195_MUTEX_MOD_DISP_DP_INTF0 21
111 #define MT8195_MUTEX_MOD_DISP_PWM0 27
112
113 #define MT2712_MUTEX_MOD_DISP_PWM2 10
114 #define MT2712_MUTEX_MOD_DISP_OVL0 11
115 #define MT2712_MUTEX_MOD_DISP_OVL1 12
116 #define MT2712_MUTEX_MOD_DISP_RDMA0 13
117 #define MT2712_MUTEX_MOD_DISP_RDMA1 14
118 #define MT2712_MUTEX_MOD_DISP_RDMA2 15
119 #define MT2712_MUTEX_MOD_DISP_WDMA0 16
120 #define MT2712_MUTEX_MOD_DISP_WDMA1 17
121 #define MT2712_MUTEX_MOD_DISP_COLOR0 18
122 #define MT2712_MUTEX_MOD_DISP_COLOR1 19
123 #define MT2712_MUTEX_MOD_DISP_AAL0 20
124 #define MT2712_MUTEX_MOD_DISP_UFOE 22
125 #define MT2712_MUTEX_MOD_DISP_PWM0 23
126 #define MT2712_MUTEX_MOD_DISP_PWM1 24
127 #define MT2712_MUTEX_MOD_DISP_OD0 25
128 #define MT2712_MUTEX_MOD2_DISP_AAL1 33
129 #define MT2712_MUTEX_MOD2_DISP_OD1 34
130
131 #define MT2701_MUTEX_MOD_DISP_OVL 3
132 #define MT2701_MUTEX_MOD_DISP_WDMA 6
133 #define MT2701_MUTEX_MOD_DISP_COLOR 7
134 #define MT2701_MUTEX_MOD_DISP_BLS 9
135 #define MT2701_MUTEX_MOD_DISP_RDMA0 10
136 #define MT2701_MUTEX_MOD_DISP_RDMA1 12
137
138 #define MT2712_MUTEX_SOF_SINGLE_MODE 0
139 #define MT2712_MUTEX_SOF_DSI0 1
140 #define MT2712_MUTEX_SOF_DSI1 2
141 #define MT2712_MUTEX_SOF_DPI0 3
142 #define MT2712_MUTEX_SOF_DPI1 4
143 #define MT2712_MUTEX_SOF_DSI2 5
144 #define MT2712_MUTEX_SOF_DSI3 6
145 #define MT8167_MUTEX_SOF_DPI0 2
146 #define MT8167_MUTEX_SOF_DPI1 3
147 #define MT8183_MUTEX_SOF_DSI0 1
148 #define MT8183_MUTEX_SOF_DPI0 2
149 #define MT8195_MUTEX_SOF_DSI0 1
150 #define MT8195_MUTEX_SOF_DSI1 2
151 #define MT8195_MUTEX_SOF_DP_INTF0 3
152 #define MT8195_MUTEX_SOF_DP_INTF1 4
153 #define MT8195_MUTEX_SOF_DPI0 6 /* for HDMI_TX */
154 #define MT8195_MUTEX_SOF_DPI1 5 /* for digital video out */
155
156 #define MT8183_MUTEX_EOF_DSI0 (MT8183_MUTEX_SOF_DSI0 << 6)
157 #define MT8183_MUTEX_EOF_DPI0 (MT8183_MUTEX_SOF_DPI0 << 6)
158 #define MT8195_MUTEX_EOF_DSI0 (MT8195_MUTEX_SOF_DSI0 << 7)
159 #define MT8195_MUTEX_EOF_DSI1 (MT8195_MUTEX_SOF_DSI1 << 7)
160 #define MT8195_MUTEX_EOF_DP_INTF0 (MT8195_MUTEX_SOF_DP_INTF0 << 7)
161 #define MT8195_MUTEX_EOF_DP_INTF1 (MT8195_MUTEX_SOF_DP_INTF1 << 7)
162 #define MT8195_MUTEX_EOF_DPI0 (MT8195_MUTEX_SOF_DPI0 << 7)
163 #define MT8195_MUTEX_EOF_DPI1 (MT8195_MUTEX_SOF_DPI1 << 7)
164
165 struct mtk_mutex {
166 int id;
167 bool claimed;
168 };
169
170 enum mtk_mutex_sof_id {
171 MUTEX_SOF_SINGLE_MODE,
172 MUTEX_SOF_DSI0,
173 MUTEX_SOF_DSI1,
174 MUTEX_SOF_DPI0,
175 MUTEX_SOF_DPI1,
176 MUTEX_SOF_DSI2,
177 MUTEX_SOF_DSI3,
178 MUTEX_SOF_DP_INTF0,
179 MUTEX_SOF_DP_INTF1,
180 DDP_MUTEX_SOF_MAX,
181 };
182
183 struct mtk_mutex_data {
184 const unsigned int *mutex_mod;
185 const unsigned int *mutex_sof;
186 const unsigned int mutex_mod_reg;
187 const unsigned int mutex_sof_reg;
188 const bool no_clk;
189 };
190
191 struct mtk_mutex_ctx {
192 struct device *dev;
193 struct clk *clk;
194 void __iomem *regs;
195 struct mtk_mutex mutex[10];
196 const struct mtk_mutex_data *data;
197 };
198
199 static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
200 [DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS,
201 [DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR,
202 [DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL,
203 [DDP_COMPONENT_RDMA0] = MT2701_MUTEX_MOD_DISP_RDMA0,
204 [DDP_COMPONENT_RDMA1] = MT2701_MUTEX_MOD_DISP_RDMA1,
205 [DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
206 };
207
208 static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
209 [DDP_COMPONENT_AAL0] = MT2712_MUTEX_MOD_DISP_AAL0,
210 [DDP_COMPONENT_AAL1] = MT2712_MUTEX_MOD2_DISP_AAL1,
211 [DDP_COMPONENT_COLOR0] = MT2712_MUTEX_MOD_DISP_COLOR0,
212 [DDP_COMPONENT_COLOR1] = MT2712_MUTEX_MOD_DISP_COLOR1,
213 [DDP_COMPONENT_OD0] = MT2712_MUTEX_MOD_DISP_OD0,
214 [DDP_COMPONENT_OD1] = MT2712_MUTEX_MOD2_DISP_OD1,
215 [DDP_COMPONENT_OVL0] = MT2712_MUTEX_MOD_DISP_OVL0,
216 [DDP_COMPONENT_OVL1] = MT2712_MUTEX_MOD_DISP_OVL1,
217 [DDP_COMPONENT_PWM0] = MT2712_MUTEX_MOD_DISP_PWM0,
218 [DDP_COMPONENT_PWM1] = MT2712_MUTEX_MOD_DISP_PWM1,
219 [DDP_COMPONENT_PWM2] = MT2712_MUTEX_MOD_DISP_PWM2,
220 [DDP_COMPONENT_RDMA0] = MT2712_MUTEX_MOD_DISP_RDMA0,
221 [DDP_COMPONENT_RDMA1] = MT2712_MUTEX_MOD_DISP_RDMA1,
222 [DDP_COMPONENT_RDMA2] = MT2712_MUTEX_MOD_DISP_RDMA2,
223 [DDP_COMPONENT_UFOE] = MT2712_MUTEX_MOD_DISP_UFOE,
224 [DDP_COMPONENT_WDMA0] = MT2712_MUTEX_MOD_DISP_WDMA0,
225 [DDP_COMPONENT_WDMA1] = MT2712_MUTEX_MOD_DISP_WDMA1,
226 };
227
228 static const unsigned int mt8167_mutex_mod[DDP_COMPONENT_ID_MAX] = {
229 [DDP_COMPONENT_AAL0] = MT8167_MUTEX_MOD_DISP_AAL,
230 [DDP_COMPONENT_CCORR] = MT8167_MUTEX_MOD_DISP_CCORR,
231 [DDP_COMPONENT_COLOR0] = MT8167_MUTEX_MOD_DISP_COLOR,
232 [DDP_COMPONENT_DITHER0] = MT8167_MUTEX_MOD_DISP_DITHER,
233 [DDP_COMPONENT_GAMMA] = MT8167_MUTEX_MOD_DISP_GAMMA,
234 [DDP_COMPONENT_OVL0] = MT8167_MUTEX_MOD_DISP_OVL0,
235 [DDP_COMPONENT_OVL1] = MT8167_MUTEX_MOD_DISP_OVL1,
236 [DDP_COMPONENT_PWM0] = MT8167_MUTEX_MOD_DISP_PWM,
237 [DDP_COMPONENT_RDMA0] = MT8167_MUTEX_MOD_DISP_RDMA0,
238 [DDP_COMPONENT_RDMA1] = MT8167_MUTEX_MOD_DISP_RDMA1,
239 [DDP_COMPONENT_UFOE] = MT8167_MUTEX_MOD_DISP_UFOE,
240 [DDP_COMPONENT_WDMA0] = MT8167_MUTEX_MOD_DISP_WDMA0,
241 };
242
243 static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
244 [DDP_COMPONENT_AAL0] = MT8173_MUTEX_MOD_DISP_AAL,
245 [DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
246 [DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1,
247 [DDP_COMPONENT_GAMMA] = MT8173_MUTEX_MOD_DISP_GAMMA,
248 [DDP_COMPONENT_OD0] = MT8173_MUTEX_MOD_DISP_OD,
249 [DDP_COMPONENT_OVL0] = MT8173_MUTEX_MOD_DISP_OVL0,
250 [DDP_COMPONENT_OVL1] = MT8173_MUTEX_MOD_DISP_OVL1,
251 [DDP_COMPONENT_PWM0] = MT8173_MUTEX_MOD_DISP_PWM0,
252 [DDP_COMPONENT_PWM1] = MT8173_MUTEX_MOD_DISP_PWM1,
253 [DDP_COMPONENT_RDMA0] = MT8173_MUTEX_MOD_DISP_RDMA0,
254 [DDP_COMPONENT_RDMA1] = MT8173_MUTEX_MOD_DISP_RDMA1,
255 [DDP_COMPONENT_RDMA2] = MT8173_MUTEX_MOD_DISP_RDMA2,
256 [DDP_COMPONENT_UFOE] = MT8173_MUTEX_MOD_DISP_UFOE,
257 [DDP_COMPONENT_WDMA0] = MT8173_MUTEX_MOD_DISP_WDMA0,
258 [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1,
259 };
260
261 static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = {
262 [DDP_COMPONENT_AAL0] = MT8183_MUTEX_MOD_DISP_AAL0,
263 [DDP_COMPONENT_CCORR] = MT8183_MUTEX_MOD_DISP_CCORR0,
264 [DDP_COMPONENT_COLOR0] = MT8183_MUTEX_MOD_DISP_COLOR0,
265 [DDP_COMPONENT_DITHER0] = MT8183_MUTEX_MOD_DISP_DITHER0,
266 [DDP_COMPONENT_GAMMA] = MT8183_MUTEX_MOD_DISP_GAMMA0,
267 [DDP_COMPONENT_OVL0] = MT8183_MUTEX_MOD_DISP_OVL0,
268 [DDP_COMPONENT_OVL_2L0] = MT8183_MUTEX_MOD_DISP_OVL0_2L,
269 [DDP_COMPONENT_OVL_2L1] = MT8183_MUTEX_MOD_DISP_OVL1_2L,
270 [DDP_COMPONENT_RDMA0] = MT8183_MUTEX_MOD_DISP_RDMA0,
271 [DDP_COMPONENT_RDMA1] = MT8183_MUTEX_MOD_DISP_RDMA1,
272 [DDP_COMPONENT_WDMA0] = MT8183_MUTEX_MOD_DISP_WDMA0,
273 };
274
275 static const unsigned int mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = {
276 [DDP_COMPONENT_AAL0] = MT8186_MUTEX_MOD_DISP_AAL0,
277 [DDP_COMPONENT_CCORR] = MT8186_MUTEX_MOD_DISP_CCORR0,
278 [DDP_COMPONENT_COLOR0] = MT8186_MUTEX_MOD_DISP_COLOR0,
279 [DDP_COMPONENT_DITHER0] = MT8186_MUTEX_MOD_DISP_DITHER0,
280 [DDP_COMPONENT_GAMMA] = MT8186_MUTEX_MOD_DISP_GAMMA0,
281 [DDP_COMPONENT_OVL0] = MT8186_MUTEX_MOD_DISP_OVL0,
282 [DDP_COMPONENT_OVL_2L0] = MT8186_MUTEX_MOD_DISP_OVL0_2L,
283 [DDP_COMPONENT_POSTMASK0] = MT8186_MUTEX_MOD_DISP_POSTMASK0,
284 [DDP_COMPONENT_RDMA0] = MT8186_MUTEX_MOD_DISP_RDMA0,
285 [DDP_COMPONENT_RDMA1] = MT8186_MUTEX_MOD_DISP_RDMA1,
286 };
287
288 static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = {
289 [DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0,
290 [DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0,
291 [DDP_COMPONENT_COLOR0] = MT8192_MUTEX_MOD_DISP_COLOR0,
292 [DDP_COMPONENT_DITHER0] = MT8192_MUTEX_MOD_DISP_DITHER0,
293 [DDP_COMPONENT_GAMMA] = MT8192_MUTEX_MOD_DISP_GAMMA0,
294 [DDP_COMPONENT_POSTMASK0] = MT8192_MUTEX_MOD_DISP_POSTMASK0,
295 [DDP_COMPONENT_OVL0] = MT8192_MUTEX_MOD_DISP_OVL0,
296 [DDP_COMPONENT_OVL_2L0] = MT8192_MUTEX_MOD_DISP_OVL0_2L,
297 [DDP_COMPONENT_OVL_2L2] = MT8192_MUTEX_MOD_DISP_OVL2_2L,
298 [DDP_COMPONENT_RDMA0] = MT8192_MUTEX_MOD_DISP_RDMA0,
299 [DDP_COMPONENT_RDMA4] = MT8192_MUTEX_MOD_DISP_RDMA4,
300 };
301
302 static const unsigned int mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
303 [DDP_COMPONENT_OVL0] = MT8195_MUTEX_MOD_DISP_OVL0,
304 [DDP_COMPONENT_WDMA0] = MT8195_MUTEX_MOD_DISP_WDMA0,
305 [DDP_COMPONENT_RDMA0] = MT8195_MUTEX_MOD_DISP_RDMA0,
306 [DDP_COMPONENT_COLOR0] = MT8195_MUTEX_MOD_DISP_COLOR0,
307 [DDP_COMPONENT_CCORR] = MT8195_MUTEX_MOD_DISP_CCORR0,
308 [DDP_COMPONENT_AAL0] = MT8195_MUTEX_MOD_DISP_AAL0,
309 [DDP_COMPONENT_GAMMA] = MT8195_MUTEX_MOD_DISP_GAMMA0,
310 [DDP_COMPONENT_DITHER0] = MT8195_MUTEX_MOD_DISP_DITHER0,
311 [DDP_COMPONENT_MERGE0] = MT8195_MUTEX_MOD_DISP_VPP_MERGE,
312 [DDP_COMPONENT_DSC0] = MT8195_MUTEX_MOD_DISP_DSC_WRAP0_CORE0,
313 [DDP_COMPONENT_DSI0] = MT8195_MUTEX_MOD_DISP_DSI0,
314 [DDP_COMPONENT_PWM0] = MT8195_MUTEX_MOD_DISP_PWM0,
315 [DDP_COMPONENT_DP_INTF0] = MT8195_MUTEX_MOD_DISP_DP_INTF0,
316 };
317
318 static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
319 [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
320 [MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
321 [MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1,
322 [MUTEX_SOF_DPI0] = MUTEX_SOF_DPI0,
323 [MUTEX_SOF_DPI1] = MUTEX_SOF_DPI1,
324 [MUTEX_SOF_DSI2] = MUTEX_SOF_DSI2,
325 [MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3,
326 };
327
328 static const unsigned int mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = {
329 [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
330 [MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
331 [MUTEX_SOF_DPI0] = MT8167_MUTEX_SOF_DPI0,
332 [MUTEX_SOF_DPI1] = MT8167_MUTEX_SOF_DPI1,
333 };
334
335 /* Add EOF setting so overlay hardware can receive frame done irq */
336 static const unsigned int mt8183_mutex_sof[DDP_MUTEX_SOF_MAX] = {
337 [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
338 [MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0 | MT8183_MUTEX_EOF_DSI0,
339 [MUTEX_SOF_DPI0] = MT8183_MUTEX_SOF_DPI0 | MT8183_MUTEX_EOF_DPI0,
340 };
341
342 static const unsigned int mt8186_mutex_sof[MUTEX_SOF_DSI3 + 1] = {
343 [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
344 [MUTEX_SOF_DSI0] = MT8186_MUTEX_SOF_DSI0 | MT8186_MUTEX_EOF_DSI0,
345 [MUTEX_SOF_DPI0] = MT8186_MUTEX_SOF_DPI0 | MT8186_MUTEX_EOF_DPI0,
346 };
347
348 /*
349 * To support refresh mode(video mode), DISP_REG_MUTEX_SOF should
350 * select the EOF source and configure the EOF plus timing from the
351 * module that provides the timing signal.
352 * So that MUTEX can not only send a STREAM_DONE event to GCE
353 * but also detect the error at end of frame(EAEOF) when EOF signal
354 * arrives.
355 */
356 static const unsigned int mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = {
357 [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
358 [MUTEX_SOF_DSI0] = MT8195_MUTEX_SOF_DSI0 | MT8195_MUTEX_EOF_DSI0,
359 [MUTEX_SOF_DSI1] = MT8195_MUTEX_SOF_DSI1 | MT8195_MUTEX_EOF_DSI1,
360 [MUTEX_SOF_DPI0] = MT8195_MUTEX_SOF_DPI0 | MT8195_MUTEX_EOF_DPI0,
361 [MUTEX_SOF_DPI1] = MT8195_MUTEX_SOF_DPI1 | MT8195_MUTEX_EOF_DPI1,
362 [MUTEX_SOF_DP_INTF0] =
363 MT8195_MUTEX_SOF_DP_INTF0 | MT8195_MUTEX_EOF_DP_INTF0,
364 [MUTEX_SOF_DP_INTF1] =
365 MT8195_MUTEX_SOF_DP_INTF1 | MT8195_MUTEX_EOF_DP_INTF1,
366 };
367
368 static const struct mtk_mutex_data mt2701_mutex_driver_data = {
369 .mutex_mod = mt2701_mutex_mod,
370 .mutex_sof = mt2712_mutex_sof,
371 .mutex_mod_reg = MT2701_MUTEX0_MOD0,
372 .mutex_sof_reg = MT2701_MUTEX0_SOF0,
373 };
374
375 static const struct mtk_mutex_data mt2712_mutex_driver_data = {
376 .mutex_mod = mt2712_mutex_mod,
377 .mutex_sof = mt2712_mutex_sof,
378 .mutex_mod_reg = MT2701_MUTEX0_MOD0,
379 .mutex_sof_reg = MT2701_MUTEX0_SOF0,
380 };
381
382 static const struct mtk_mutex_data mt8167_mutex_driver_data = {
383 .mutex_mod = mt8167_mutex_mod,
384 .mutex_sof = mt8167_mutex_sof,
385 .mutex_mod_reg = MT2701_MUTEX0_MOD0,
386 .mutex_sof_reg = MT2701_MUTEX0_SOF0,
387 .no_clk = true,
388 };
389
390 static const struct mtk_mutex_data mt8173_mutex_driver_data = {
391 .mutex_mod = mt8173_mutex_mod,
392 .mutex_sof = mt2712_mutex_sof,
393 .mutex_mod_reg = MT2701_MUTEX0_MOD0,
394 .mutex_sof_reg = MT2701_MUTEX0_SOF0,
395 };
396
397 static const struct mtk_mutex_data mt8183_mutex_driver_data = {
398 .mutex_mod = mt8183_mutex_mod,
399 .mutex_sof = mt8183_mutex_sof,
400 .mutex_mod_reg = MT8183_MUTEX0_MOD0,
401 .mutex_sof_reg = MT8183_MUTEX0_SOF0,
402 .no_clk = true,
403 };
404
405 static const struct mtk_mutex_data mt8186_mutex_driver_data = {
406 .mutex_mod = mt8186_mutex_mod,
407 .mutex_sof = mt8186_mutex_sof,
408 .mutex_mod_reg = MT8183_MUTEX0_MOD0,
409 .mutex_sof_reg = MT8183_MUTEX0_SOF0,
410 };
411
412 static const struct mtk_mutex_data mt8192_mutex_driver_data = {
413 .mutex_mod = mt8192_mutex_mod,
414 .mutex_sof = mt8183_mutex_sof,
415 .mutex_mod_reg = MT8183_MUTEX0_MOD0,
416 .mutex_sof_reg = MT8183_MUTEX0_SOF0,
417 };
418
419 static const struct mtk_mutex_data mt8195_mutex_driver_data = {
420 .mutex_mod = mt8195_mutex_mod,
421 .mutex_sof = mt8195_mutex_sof,
422 .mutex_mod_reg = MT8183_MUTEX0_MOD0,
423 .mutex_sof_reg = MT8183_MUTEX0_SOF0,
424 };
425
mtk_mutex_get(struct device * dev)426 struct mtk_mutex *mtk_mutex_get(struct device *dev)
427 {
428 struct mtk_mutex_ctx *mtx = dev_get_drvdata(dev);
429 int i;
430
431 for (i = 0; i < 10; i++)
432 if (!mtx->mutex[i].claimed) {
433 mtx->mutex[i].claimed = true;
434 return &mtx->mutex[i];
435 }
436
437 return ERR_PTR(-EBUSY);
438 }
439 EXPORT_SYMBOL_GPL(mtk_mutex_get);
440
mtk_mutex_put(struct mtk_mutex * mutex)441 void mtk_mutex_put(struct mtk_mutex *mutex)
442 {
443 struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
444 mutex[mutex->id]);
445
446 WARN_ON(&mtx->mutex[mutex->id] != mutex);
447
448 mutex->claimed = false;
449 }
450 EXPORT_SYMBOL_GPL(mtk_mutex_put);
451
mtk_mutex_prepare(struct mtk_mutex * mutex)452 int mtk_mutex_prepare(struct mtk_mutex *mutex)
453 {
454 struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
455 mutex[mutex->id]);
456 return clk_prepare_enable(mtx->clk);
457 }
458 EXPORT_SYMBOL_GPL(mtk_mutex_prepare);
459
mtk_mutex_unprepare(struct mtk_mutex * mutex)460 void mtk_mutex_unprepare(struct mtk_mutex *mutex)
461 {
462 struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
463 mutex[mutex->id]);
464 clk_disable_unprepare(mtx->clk);
465 }
466 EXPORT_SYMBOL_GPL(mtk_mutex_unprepare);
467
mtk_mutex_add_comp(struct mtk_mutex * mutex,enum mtk_ddp_comp_id id)468 void mtk_mutex_add_comp(struct mtk_mutex *mutex,
469 enum mtk_ddp_comp_id id)
470 {
471 struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
472 mutex[mutex->id]);
473 unsigned int reg;
474 unsigned int sof_id;
475 unsigned int offset;
476
477 WARN_ON(&mtx->mutex[mutex->id] != mutex);
478
479 switch (id) {
480 case DDP_COMPONENT_DSI0:
481 sof_id = MUTEX_SOF_DSI0;
482 break;
483 case DDP_COMPONENT_DSI1:
484 sof_id = MUTEX_SOF_DSI0;
485 break;
486 case DDP_COMPONENT_DSI2:
487 sof_id = MUTEX_SOF_DSI2;
488 break;
489 case DDP_COMPONENT_DSI3:
490 sof_id = MUTEX_SOF_DSI3;
491 break;
492 case DDP_COMPONENT_DPI0:
493 sof_id = MUTEX_SOF_DPI0;
494 break;
495 case DDP_COMPONENT_DPI1:
496 sof_id = MUTEX_SOF_DPI1;
497 break;
498 case DDP_COMPONENT_DP_INTF0:
499 sof_id = MUTEX_SOF_DP_INTF0;
500 break;
501 default:
502 if (mtx->data->mutex_mod[id] < 32) {
503 offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
504 mutex->id);
505 reg = readl_relaxed(mtx->regs + offset);
506 reg |= 1 << mtx->data->mutex_mod[id];
507 writel_relaxed(reg, mtx->regs + offset);
508 } else {
509 offset = DISP_REG_MUTEX_MOD2(mutex->id);
510 reg = readl_relaxed(mtx->regs + offset);
511 reg |= 1 << (mtx->data->mutex_mod[id] - 32);
512 writel_relaxed(reg, mtx->regs + offset);
513 }
514 return;
515 }
516
517 writel_relaxed(mtx->data->mutex_sof[sof_id],
518 mtx->regs +
519 DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg, mutex->id));
520 }
521 EXPORT_SYMBOL_GPL(mtk_mutex_add_comp);
522
mtk_mutex_remove_comp(struct mtk_mutex * mutex,enum mtk_ddp_comp_id id)523 void mtk_mutex_remove_comp(struct mtk_mutex *mutex,
524 enum mtk_ddp_comp_id id)
525 {
526 struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
527 mutex[mutex->id]);
528 unsigned int reg;
529 unsigned int offset;
530
531 WARN_ON(&mtx->mutex[mutex->id] != mutex);
532
533 switch (id) {
534 case DDP_COMPONENT_DSI0:
535 case DDP_COMPONENT_DSI1:
536 case DDP_COMPONENT_DSI2:
537 case DDP_COMPONENT_DSI3:
538 case DDP_COMPONENT_DPI0:
539 case DDP_COMPONENT_DPI1:
540 case DDP_COMPONENT_DP_INTF0:
541 writel_relaxed(MUTEX_SOF_SINGLE_MODE,
542 mtx->regs +
543 DISP_REG_MUTEX_SOF(mtx->data->mutex_sof_reg,
544 mutex->id));
545 break;
546 default:
547 if (mtx->data->mutex_mod[id] < 32) {
548 offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
549 mutex->id);
550 reg = readl_relaxed(mtx->regs + offset);
551 reg &= ~(1 << mtx->data->mutex_mod[id]);
552 writel_relaxed(reg, mtx->regs + offset);
553 } else {
554 offset = DISP_REG_MUTEX_MOD2(mutex->id);
555 reg = readl_relaxed(mtx->regs + offset);
556 reg &= ~(1 << (mtx->data->mutex_mod[id] - 32));
557 writel_relaxed(reg, mtx->regs + offset);
558 }
559 break;
560 }
561 }
562 EXPORT_SYMBOL_GPL(mtk_mutex_remove_comp);
563
mtk_mutex_enable(struct mtk_mutex * mutex)564 void mtk_mutex_enable(struct mtk_mutex *mutex)
565 {
566 struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
567 mutex[mutex->id]);
568
569 WARN_ON(&mtx->mutex[mutex->id] != mutex);
570
571 writel(1, mtx->regs + DISP_REG_MUTEX_EN(mutex->id));
572 }
573 EXPORT_SYMBOL_GPL(mtk_mutex_enable);
574
mtk_mutex_disable(struct mtk_mutex * mutex)575 void mtk_mutex_disable(struct mtk_mutex *mutex)
576 {
577 struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
578 mutex[mutex->id]);
579
580 WARN_ON(&mtx->mutex[mutex->id] != mutex);
581
582 writel(0, mtx->regs + DISP_REG_MUTEX_EN(mutex->id));
583 }
584 EXPORT_SYMBOL_GPL(mtk_mutex_disable);
585
mtk_mutex_acquire(struct mtk_mutex * mutex)586 void mtk_mutex_acquire(struct mtk_mutex *mutex)
587 {
588 struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
589 mutex[mutex->id]);
590 u32 tmp;
591
592 writel(1, mtx->regs + DISP_REG_MUTEX_EN(mutex->id));
593 writel(1, mtx->regs + DISP_REG_MUTEX(mutex->id));
594 if (readl_poll_timeout_atomic(mtx->regs + DISP_REG_MUTEX(mutex->id),
595 tmp, tmp & INT_MUTEX, 1, 10000))
596 pr_err("could not acquire mutex %d\n", mutex->id);
597 }
598 EXPORT_SYMBOL_GPL(mtk_mutex_acquire);
599
mtk_mutex_release(struct mtk_mutex * mutex)600 void mtk_mutex_release(struct mtk_mutex *mutex)
601 {
602 struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
603 mutex[mutex->id]);
604
605 writel(0, mtx->regs + DISP_REG_MUTEX(mutex->id));
606 }
607 EXPORT_SYMBOL_GPL(mtk_mutex_release);
608
mtk_mutex_probe(struct platform_device * pdev)609 static int mtk_mutex_probe(struct platform_device *pdev)
610 {
611 struct device *dev = &pdev->dev;
612 struct mtk_mutex_ctx *mtx;
613 struct resource *regs;
614 int i;
615
616 mtx = devm_kzalloc(dev, sizeof(*mtx), GFP_KERNEL);
617 if (!mtx)
618 return -ENOMEM;
619
620 for (i = 0; i < 10; i++)
621 mtx->mutex[i].id = i;
622
623 mtx->data = of_device_get_match_data(dev);
624
625 if (!mtx->data->no_clk) {
626 mtx->clk = devm_clk_get(dev, NULL);
627 if (IS_ERR(mtx->clk)) {
628 if (PTR_ERR(mtx->clk) != -EPROBE_DEFER)
629 dev_err(dev, "Failed to get clock\n");
630 return PTR_ERR(mtx->clk);
631 }
632 }
633
634 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
635 mtx->regs = devm_ioremap_resource(dev, regs);
636 if (IS_ERR(mtx->regs)) {
637 dev_err(dev, "Failed to map mutex registers\n");
638 return PTR_ERR(mtx->regs);
639 }
640
641 platform_set_drvdata(pdev, mtx);
642
643 return 0;
644 }
645
mtk_mutex_remove(struct platform_device * pdev)646 static int mtk_mutex_remove(struct platform_device *pdev)
647 {
648 return 0;
649 }
650
651 static const struct of_device_id mutex_driver_dt_match[] = {
652 { .compatible = "mediatek,mt2701-disp-mutex",
653 .data = &mt2701_mutex_driver_data},
654 { .compatible = "mediatek,mt2712-disp-mutex",
655 .data = &mt2712_mutex_driver_data},
656 { .compatible = "mediatek,mt8167-disp-mutex",
657 .data = &mt8167_mutex_driver_data},
658 { .compatible = "mediatek,mt8173-disp-mutex",
659 .data = &mt8173_mutex_driver_data},
660 { .compatible = "mediatek,mt8183-disp-mutex",
661 .data = &mt8183_mutex_driver_data},
662 { .compatible = "mediatek,mt8186-disp-mutex",
663 .data = &mt8186_mutex_driver_data},
664 { .compatible = "mediatek,mt8192-disp-mutex",
665 .data = &mt8192_mutex_driver_data},
666 { .compatible = "mediatek,mt8195-disp-mutex",
667 .data = &mt8195_mutex_driver_data},
668 {},
669 };
670 MODULE_DEVICE_TABLE(of, mutex_driver_dt_match);
671
672 static struct platform_driver mtk_mutex_driver = {
673 .probe = mtk_mutex_probe,
674 .remove = mtk_mutex_remove,
675 .driver = {
676 .name = "mediatek-mutex",
677 .owner = THIS_MODULE,
678 .of_match_table = mutex_driver_dt_match,
679 },
680 };
681
682 builtin_platform_driver(mtk_mutex_driver);
683