xref: /linux/drivers/media/platform/qcom/iris/iris_vpu3x.c (revision 55a42f78ffd386e01a5404419f8c5ded7db70a21)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  * Copyright (c) 2025 Linaro Ltd
5  */
6 
7 #include <linux/iopoll.h>
8 #include <linux/reset.h>
9 
10 #include "iris_instance.h"
11 #include "iris_vpu_common.h"
12 #include "iris_vpu_register_defines.h"
13 
14 #define WRAPPER_TZ_BASE_OFFS			0x000C0000
15 #define AON_BASE_OFFS				0x000E0000
16 #define AON_MVP_NOC_RESET			0x0001F000
17 
18 #define WRAPPER_DEBUG_BRIDGE_LPI_CONTROL	(WRAPPER_BASE_OFFS + 0x54)
19 #define WRAPPER_DEBUG_BRIDGE_LPI_STATUS		(WRAPPER_BASE_OFFS + 0x58)
20 #define WRAPPER_IRIS_CPU_NOC_LPI_CONTROL	(WRAPPER_BASE_OFFS + 0x5C)
21 #define REQ_POWER_DOWN_PREP			BIT(0)
22 #define WRAPPER_IRIS_CPU_NOC_LPI_STATUS		(WRAPPER_BASE_OFFS + 0x60)
23 #define NOC_LPI_STATUS_DONE			BIT(0) /* Indicates the NOC handshake is complete */
24 #define NOC_LPI_STATUS_DENY			BIT(1) /* Indicates the NOC handshake is denied */
25 #define NOC_LPI_STATUS_ACTIVE		BIT(2) /* Indicates the NOC is active */
26 #define WRAPPER_CORE_CLOCK_CONFIG		(WRAPPER_BASE_OFFS + 0x88)
27 #define CORE_CLK_RUN				0x0
28 /* VPU v3.5 */
29 #define WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0	(WRAPPER_BASE_OFFS + 0x78)
30 
31 #define WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG		(WRAPPER_TZ_BASE_OFFS + 0x14)
32 #define CTL_AXI_CLK_HALT			BIT(0)
33 #define CTL_CLK_HALT				BIT(1)
34 
35 #define WRAPPER_TZ_QNS4PDXFIFO_RESET		(WRAPPER_TZ_BASE_OFFS + 0x18)
36 #define RESET_HIGH				BIT(0)
37 
38 #define CPU_CS_AHB_BRIDGE_SYNC_RESET		(CPU_CS_BASE_OFFS + 0x160)
39 #define CORE_BRIDGE_SW_RESET			BIT(0)
40 #define CORE_BRIDGE_HW_RESET_DISABLE		BIT(1)
41 
42 #define CPU_CS_X2RPMH				(CPU_CS_BASE_OFFS + 0x168)
43 #define MSK_SIGNAL_FROM_TENSILICA		BIT(0)
44 #define MSK_CORE_POWER_ON			BIT(1)
45 
46 #define AON_WRAPPER_MVP_NOC_RESET_REQ		(AON_MVP_NOC_RESET + 0x000)
47 #define VIDEO_NOC_RESET_REQ			(BIT(0) | BIT(1))
48 
49 #define AON_WRAPPER_MVP_NOC_RESET_ACK		(AON_MVP_NOC_RESET + 0x004)
50 
51 #define VCODEC_SS_IDLE_STATUSN			(VCODEC_BASE_OFFS + 0x70)
52 
53 #define AON_WRAPPER_MVP_NOC_LPI_CONTROL		(AON_BASE_OFFS)
54 #define AON_WRAPPER_MVP_NOC_LPI_STATUS		(AON_BASE_OFFS + 0x4)
55 
56 #define AON_WRAPPER_MVP_NOC_CORE_SW_RESET	(AON_BASE_OFFS + 0x18)
57 #define SW_RESET				BIT(0)
58 #define AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL	(AON_BASE_OFFS + 0x20)
59 #define NOC_HALT				BIT(0)
60 #define AON_WRAPPER_SPARE			(AON_BASE_OFFS + 0x28)
61 #define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL	(AON_BASE_OFFS + 0x2C)
62 #define AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS	(AON_BASE_OFFS + 0x30)
63 
64 static bool iris_vpu3x_hw_power_collapsed(struct iris_core *core)
65 {
66 	u32 value, pwr_status;
67 
68 	value = readl(core->reg_base + WRAPPER_CORE_POWER_STATUS);
69 	pwr_status = value & BIT(1);
70 
71 	return pwr_status ? false : true;
72 }
73 
74 static void iris_vpu3_power_off_hardware(struct iris_core *core)
75 {
76 	u32 reg_val = 0, value, i;
77 	int ret;
78 
79 	if (iris_vpu3x_hw_power_collapsed(core))
80 		goto disable_power;
81 
82 	dev_err(core->dev, "video hw is power on\n");
83 
84 	value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
85 	if (value)
86 		writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
87 
88 	for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) {
89 		ret = readl_poll_timeout(core->reg_base + VCODEC_SS_IDLE_STATUSN + 4 * i,
90 					 reg_val, reg_val & 0x400000, 2000, 20000);
91 		if (ret)
92 			goto disable_power;
93 	}
94 
95 	writel(VIDEO_NOC_RESET_REQ, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ);
96 
97 	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK,
98 				 reg_val, reg_val & 0x3, 200, 2000);
99 	if (ret)
100 		goto disable_power;
101 
102 	writel(0x0, core->reg_base + AON_WRAPPER_MVP_NOC_RESET_REQ);
103 
104 	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_RESET_ACK,
105 				 reg_val, !(reg_val & 0x3), 200, 2000);
106 	if (ret)
107 		goto disable_power;
108 
109 	writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE,
110 	       core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);
111 	writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);
112 	writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);
113 
114 disable_power:
115 	iris_vpu_power_off_hw(core);
116 }
117 
118 static void iris_vpu33_power_off_hardware(struct iris_core *core)
119 {
120 	bool handshake_done = false, handshake_busy = false;
121 	u32 reg_val = 0, value, i;
122 	u32 count = 0;
123 	int ret;
124 
125 	if (iris_vpu3x_hw_power_collapsed(core))
126 		goto disable_power;
127 
128 	dev_err(core->dev, "video hw is power on\n");
129 
130 	value = readl(core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
131 	if (value)
132 		writel(CORE_CLK_RUN, core->reg_base + WRAPPER_CORE_CLOCK_CONFIG);
133 
134 	for (i = 0; i < core->iris_platform_data->num_vpp_pipe; i++) {
135 		ret = readl_poll_timeout(core->reg_base + VCODEC_SS_IDLE_STATUSN + 4 * i,
136 					 reg_val, reg_val & 0x400000, 2000, 20000);
137 		if (ret)
138 			goto disable_power;
139 	}
140 
141 	/* Retry up to 1000 times as recommended by hardware documentation */
142 	do {
143 		/* set MNoC to low power */
144 		writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL);
145 
146 		udelay(15);
147 
148 		value = readl(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS);
149 
150 		handshake_done = value & NOC_LPI_STATUS_DONE;
151 		handshake_busy = value & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE);
152 
153 		if (handshake_done || !handshake_busy)
154 			break;
155 
156 		writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL);
157 
158 		udelay(15);
159 
160 	} while (++count < 1000);
161 
162 	if (!handshake_done && handshake_busy)
163 		dev_err(core->dev, "LPI handshake timeout\n");
164 
165 	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_NOC_LPI_STATUS,
166 				 reg_val, reg_val & BIT(0), 200, 2000);
167 	if (ret)
168 		goto disable_power;
169 
170 	writel(0, core->reg_base + AON_WRAPPER_MVP_NOC_LPI_CONTROL);
171 
172 	writel(CORE_BRIDGE_SW_RESET | CORE_BRIDGE_HW_RESET_DISABLE,
173 	       core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);
174 	writel(CORE_BRIDGE_HW_RESET_DISABLE, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);
175 	writel(0x0, core->reg_base + CPU_CS_AHB_BRIDGE_SYNC_RESET);
176 
177 disable_power:
178 	iris_vpu_power_off_hw(core);
179 }
180 
181 static int iris_vpu33_power_off_controller(struct iris_core *core)
182 {
183 	u32 xo_rst_tbl_size = core->iris_platform_data->controller_rst_tbl_size;
184 	u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size;
185 	u32 val = 0;
186 	int ret;
187 
188 	writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH);
189 
190 	writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL);
191 
192 	ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS,
193 				 val, val & BIT(0), 200, 2000);
194 	if (ret)
195 		goto disable_power;
196 
197 	writel(0x0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL);
198 
199 	ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS,
200 				 val, val == 0, 200, 2000);
201 	if (ret)
202 		goto disable_power;
203 
204 	writel(CTL_AXI_CLK_HALT | CTL_CLK_HALT,
205 	       core->reg_base + WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG);
206 	writel(RESET_HIGH, core->reg_base + WRAPPER_TZ_QNS4PDXFIFO_RESET);
207 	writel(0x0, core->reg_base + WRAPPER_TZ_QNS4PDXFIFO_RESET);
208 	writel(0x0, core->reg_base + WRAPPER_TZ_CTL_AXI_CLOCK_CONFIG);
209 
210 	reset_control_bulk_reset(clk_rst_tbl_size, core->resets);
211 
212 	/* Disable MVP NoC clock */
213 	val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL);
214 	val |= NOC_HALT;
215 	writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL);
216 
217 	/* enable MVP NoC reset */
218 	val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET);
219 	val |= SW_RESET;
220 	writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET);
221 
222 	/* poll AON spare register bit0 to become zero with 50ms timeout */
223 	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_SPARE,
224 				 val, (val & BIT(0)) == 0, 1000, 50000);
225 	if (ret)
226 		goto disable_power;
227 
228 	/* enable bit(1) to avoid cvp noc xo reset */
229 	val = readl(core->reg_base + AON_WRAPPER_SPARE);
230 	val |= BIT(1);
231 	writel(val, core->reg_base + AON_WRAPPER_SPARE);
232 
233 	reset_control_bulk_assert(xo_rst_tbl_size, core->controller_resets);
234 
235 	/* De-assert MVP NoC reset */
236 	val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET);
237 	val &= ~SW_RESET;
238 	writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_SW_RESET);
239 
240 	usleep_range(80, 100);
241 
242 	reset_control_bulk_deassert(xo_rst_tbl_size, core->controller_resets);
243 
244 	/* reset AON spare register */
245 	writel(0, core->reg_base + AON_WRAPPER_SPARE);
246 
247 	/* Enable MVP NoC clock */
248 	val = readl(core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL);
249 	val &= ~NOC_HALT;
250 	writel(val, core->reg_base + AON_WRAPPER_MVP_NOC_CORE_CLK_CONTROL);
251 
252 	iris_disable_unprepare_clock(core, IRIS_CTRL_CLK);
253 
254 disable_power:
255 	iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
256 	iris_disable_unprepare_clock(core, IRIS_AXI_CLK);
257 
258 	return 0;
259 }
260 
261 static int iris_vpu35_power_on_hw(struct iris_core *core)
262 {
263 	int ret;
264 
265 	ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]);
266 	if (ret)
267 		return ret;
268 
269 	ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK);
270 	if (ret)
271 		goto err_disable_power;
272 
273 	ret = iris_prepare_enable_clock(core, IRIS_HW_FREERUN_CLK);
274 	if (ret)
275 		goto err_disable_axi_clk;
276 
277 	ret = iris_prepare_enable_clock(core, IRIS_HW_CLK);
278 	if (ret)
279 		goto err_disable_hw_free_clk;
280 
281 	ret = dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], true);
282 	if (ret)
283 		goto err_disable_hw_clk;
284 
285 	return 0;
286 
287 err_disable_hw_clk:
288 	iris_disable_unprepare_clock(core, IRIS_HW_CLK);
289 err_disable_hw_free_clk:
290 	iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK);
291 err_disable_axi_clk:
292 	iris_disable_unprepare_clock(core, IRIS_AXI_CLK);
293 err_disable_power:
294 	iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]);
295 
296 	return ret;
297 }
298 
299 static void iris_vpu35_power_off_hw(struct iris_core *core)
300 {
301 	iris_vpu33_power_off_hardware(core);
302 
303 	iris_disable_unprepare_clock(core, IRIS_HW_FREERUN_CLK);
304 	iris_disable_unprepare_clock(core, IRIS_AXI_CLK);
305 }
306 
307 static int iris_vpu35_power_off_controller(struct iris_core *core)
308 {
309 	u32 clk_rst_tbl_size = core->iris_platform_data->clk_rst_tbl_size;
310 	unsigned int count = 0;
311 	u32 val = 0;
312 	bool handshake_done, handshake_busy;
313 	int ret;
314 
315 	writel(MSK_SIGNAL_FROM_TENSILICA | MSK_CORE_POWER_ON, core->reg_base + CPU_CS_X2RPMH);
316 
317 	writel(REQ_POWER_DOWN_PREP, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL);
318 
319 	ret = readl_poll_timeout(core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_STATUS,
320 				 val, val & BIT(0), 200, 2000);
321 	if (ret)
322 		goto disable_power;
323 
324 	writel(0, core->reg_base + WRAPPER_IRIS_CPU_NOC_LPI_CONTROL);
325 
326 	/* Retry up to 1000 times as recommended by hardware documentation */
327 	do {
328 		/* set MNoC to low power */
329 		writel(REQ_POWER_DOWN_PREP, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL);
330 
331 		udelay(15);
332 
333 		val = readl(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS);
334 
335 		handshake_done = val & NOC_LPI_STATUS_DONE;
336 		handshake_busy = val & (NOC_LPI_STATUS_DENY | NOC_LPI_STATUS_ACTIVE);
337 
338 		if (handshake_done || !handshake_busy)
339 			break;
340 
341 		writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL);
342 
343 		udelay(15);
344 
345 	} while (++count < 1000);
346 
347 	if (!handshake_done && handshake_busy)
348 		dev_err(core->dev, "LPI handshake timeout\n");
349 
350 	ret = readl_poll_timeout(core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_STATUS,
351 				 val, val & BIT(0), 200, 2000);
352 	if (ret)
353 		goto disable_power;
354 
355 	writel(0, core->reg_base + AON_WRAPPER_MVP_VIDEO_CTL_NOC_LPI_CONTROL);
356 
357 	writel(0, core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_CONTROL);
358 
359 	ret = readl_poll_timeout(core->reg_base + WRAPPER_DEBUG_BRIDGE_LPI_STATUS,
360 				 val, val == 0, 200, 2000);
361 	if (ret)
362 		goto disable_power;
363 
364 disable_power:
365 	iris_disable_unprepare_clock(core, IRIS_CTRL_CLK);
366 	iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK);
367 	iris_disable_unprepare_clock(core, IRIS_AXI1_CLK);
368 
369 	iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
370 
371 	reset_control_bulk_reset(clk_rst_tbl_size, core->resets);
372 
373 	return 0;
374 }
375 
376 static int iris_vpu35_power_on_controller(struct iris_core *core)
377 {
378 	int ret;
379 
380 	ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
381 	if (ret)
382 		return ret;
383 
384 	ret = iris_prepare_enable_clock(core, IRIS_AXI1_CLK);
385 	if (ret)
386 		goto err_disable_power;
387 
388 	ret = iris_prepare_enable_clock(core, IRIS_CTRL_FREERUN_CLK);
389 	if (ret)
390 		goto err_disable_axi1_clk;
391 
392 	ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK);
393 	if (ret)
394 		goto err_disable_ctrl_free_clk;
395 
396 	return 0;
397 
398 err_disable_ctrl_free_clk:
399 	iris_disable_unprepare_clock(core, IRIS_CTRL_FREERUN_CLK);
400 err_disable_axi1_clk:
401 	iris_disable_unprepare_clock(core, IRIS_AXI1_CLK);
402 err_disable_power:
403 	iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
404 
405 	return ret;
406 }
407 
408 static void iris_vpu35_program_bootup_registers(struct iris_core *core)
409 {
410 	writel(0x1, core->reg_base + WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0);
411 }
412 
413 static u64 iris_vpu3x_calculate_frequency(struct iris_inst *inst, size_t data_size)
414 {
415 	struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
416 	struct v4l2_format *inp_f = inst->fmt_src;
417 	u32 height, width, mbs_per_second, mbpf;
418 	u64 fw_cycles, fw_vpp_cycles;
419 	u64 vsp_cycles, vpp_cycles;
420 	u32 fps = DEFAULT_FPS;
421 
422 	width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
423 	height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
424 
425 	mbpf = NUM_MBS_PER_FRAME(height, width);
426 	mbs_per_second = mbpf * fps;
427 
428 	fw_cycles = fps * caps->mb_cycles_fw;
429 	fw_vpp_cycles = fps * caps->mb_cycles_fw_vpp;
430 
431 	vpp_cycles = mult_frac(mbs_per_second, caps->mb_cycles_vpp, (u32)inst->fw_caps[PIPE].value);
432 	/* 21 / 20 is minimum overhead factor */
433 	vpp_cycles += max(div_u64(vpp_cycles, 20), fw_vpp_cycles);
434 
435 	/* 1.059 is multi-pipe overhead */
436 	if (inst->fw_caps[PIPE].value > 1)
437 		vpp_cycles += div_u64(vpp_cycles * 59, 1000);
438 
439 	vsp_cycles = fps * data_size * 8;
440 	vsp_cycles = div_u64(vsp_cycles, 2);
441 	/* VSP FW overhead 1.05 */
442 	vsp_cycles = div_u64(vsp_cycles * 21, 20);
443 
444 	if (inst->fw_caps[STAGE].value == STAGE_1)
445 		vsp_cycles = vsp_cycles * 3;
446 
447 	return max3(vpp_cycles, vsp_cycles, fw_cycles);
448 }
449 
450 const struct vpu_ops iris_vpu3_ops = {
451 	.power_off_hw = iris_vpu3_power_off_hardware,
452 	.power_on_hw = iris_vpu_power_on_hw,
453 	.power_off_controller = iris_vpu_power_off_controller,
454 	.power_on_controller = iris_vpu_power_on_controller,
455 	.calc_freq = iris_vpu3x_calculate_frequency,
456 };
457 
458 const struct vpu_ops iris_vpu33_ops = {
459 	.power_off_hw = iris_vpu33_power_off_hardware,
460 	.power_on_hw = iris_vpu_power_on_hw,
461 	.power_off_controller = iris_vpu33_power_off_controller,
462 	.power_on_controller = iris_vpu_power_on_controller,
463 	.calc_freq = iris_vpu3x_calculate_frequency,
464 };
465 
466 const struct vpu_ops iris_vpu35_ops = {
467 	.power_off_hw = iris_vpu35_power_off_hw,
468 	.power_on_hw = iris_vpu35_power_on_hw,
469 	.power_off_controller = iris_vpu35_power_off_controller,
470 	.power_on_controller = iris_vpu35_power_on_controller,
471 	.program_bootup_registers = iris_vpu35_program_bootup_registers,
472 	.calc_freq = iris_vpu3x_calculate_frequency,
473 };
474