xref: /linux/drivers/media/platform/amd/isp4/isp4_interface.c (revision 8c13415c8a4383447c21ec832b20b3b283f0e01a)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2025 Advanced Micro Devices, Inc.
4  */
5 
6 #include <linux/iopoll.h>
7 
8 #include "isp4_debug.h"
9 #include "isp4_fw_cmd_resp.h"
10 #include "isp4_hw_reg.h"
11 #include "isp4_interface.h"
12 
13 #define ISP4IF_FW_RESP_RB_IRQ_EN_MASK \
14 	(ISP_SYS_INT0_EN__SYS_INT_RINGBUFFER_WPT9_EN_MASK\
15 	 | ISP_SYS_INT0_EN__SYS_INT_RINGBUFFER_WPT12_EN_MASK)
16 
17 #define ISP4IF_FW_CMD_TIMEOUT (HZ / 2)
18 
19 struct isp4if_rb_config {
20 	const char *name;
21 	u32 index;
22 	u32 reg_rptr;
23 	u32 reg_wptr;
24 	u32 reg_base_lo;
25 	u32 reg_base_hi;
26 	u32 reg_size;
27 	u32 val_size;
28 	u64 base_mc_addr;
29 	void *base_sys_addr;
30 };
31 
32 /* FW cmd ring buffer configuration */
33 static struct isp4if_rb_config isp4if_cmd_rb_config[ISP4IF_STREAM_ID_MAX] = {
34 	{
35 		.name = "CMD_RB_GBL0",
36 		.index = 3,
37 		.reg_rptr = ISP_RB_RPTR4,
38 		.reg_wptr = ISP_RB_WPTR4,
39 		.reg_base_lo = ISP_RB_BASE_LO4,
40 		.reg_base_hi = ISP_RB_BASE_HI4,
41 		.reg_size = ISP_RB_SIZE4,
42 	},
43 	{
44 		.name = "CMD_RB_STR1",
45 		.index = 0,
46 		.reg_rptr = ISP_RB_RPTR1,
47 		.reg_wptr = ISP_RB_WPTR1,
48 		.reg_base_lo = ISP_RB_BASE_LO1,
49 		.reg_base_hi = ISP_RB_BASE_HI1,
50 		.reg_size = ISP_RB_SIZE1,
51 	},
52 	{
53 		.name = "CMD_RB_STR2",
54 		.index = 1,
55 		.reg_rptr = ISP_RB_RPTR2,
56 		.reg_wptr = ISP_RB_WPTR2,
57 		.reg_base_lo = ISP_RB_BASE_LO2,
58 		.reg_base_hi = ISP_RB_BASE_HI2,
59 		.reg_size = ISP_RB_SIZE2,
60 	},
61 	{
62 		.name = "CMD_RB_STR3",
63 		.index = 2,
64 		.reg_rptr = ISP_RB_RPTR3,
65 		.reg_wptr = ISP_RB_WPTR3,
66 		.reg_base_lo = ISP_RB_BASE_LO3,
67 		.reg_base_hi = ISP_RB_BASE_HI3,
68 		.reg_size = ISP_RB_SIZE3,
69 	},
70 };
71 
72 /* FW resp ring buffer configuration */
73 static struct isp4if_rb_config isp4if_resp_rb_config[ISP4IF_STREAM_ID_MAX] = {
74 	{
75 		.name = "RES_RB_GBL0",
76 		.index = 3,
77 		.reg_rptr = ISP_RB_RPTR12,
78 		.reg_wptr = ISP_RB_WPTR12,
79 		.reg_base_lo = ISP_RB_BASE_LO12,
80 		.reg_base_hi = ISP_RB_BASE_HI12,
81 		.reg_size = ISP_RB_SIZE12,
82 	},
83 	{
84 		.name = "RES_RB_STR1",
85 		.index = 0,
86 		.reg_rptr = ISP_RB_RPTR9,
87 		.reg_wptr = ISP_RB_WPTR9,
88 		.reg_base_lo = ISP_RB_BASE_LO9,
89 		.reg_base_hi = ISP_RB_BASE_HI9,
90 		.reg_size = ISP_RB_SIZE9,
91 	},
92 	{
93 		.name = "RES_RB_STR2",
94 		.index = 1,
95 		.reg_rptr = ISP_RB_RPTR10,
96 		.reg_wptr = ISP_RB_WPTR10,
97 		.reg_base_lo = ISP_RB_BASE_LO10,
98 		.reg_base_hi = ISP_RB_BASE_HI10,
99 		.reg_size = ISP_RB_SIZE10,
100 	},
101 	{
102 		.name = "RES_RB_STR3",
103 		.index = 2,
104 		.reg_rptr = ISP_RB_RPTR11,
105 		.reg_wptr = ISP_RB_WPTR11,
106 		.reg_base_lo = ISP_RB_BASE_LO11,
107 		.reg_base_hi = ISP_RB_BASE_HI11,
108 		.reg_size = ISP_RB_SIZE11,
109 	},
110 };
111 
112 /* FW log ring buffer configuration */
113 static struct isp4if_rb_config isp4if_log_rb_config = {
114 	.name = "LOG_RB",
115 	.index = 0,
116 	.reg_rptr = ISP_LOG_RB_RPTR0,
117 	.reg_wptr = ISP_LOG_RB_WPTR0,
118 	.reg_base_lo = ISP_LOG_RB_BASE_LO0,
119 	.reg_base_hi = ISP_LOG_RB_BASE_HI0,
120 	.reg_size = ISP_LOG_RB_SIZE0,
121 };
122 
123 static struct isp4if_gpu_mem_info *
124 isp4if_gpu_mem_alloc(struct isp4_interface *ispif, u32 mem_size)
125 {
126 	struct isp4if_gpu_mem_info *mem_info;
127 	struct device *dev = ispif->dev;
128 	int ret;
129 
130 	mem_info = kmalloc_obj(*mem_info, GFP_KERNEL);
131 	if (!mem_info)
132 		return NULL;
133 
134 	mem_info->mem_size = mem_size;
135 	ret = isp_kernel_buffer_alloc(dev, mem_info->mem_size,
136 				      &mem_info->mem_handle,
137 				      &mem_info->gpu_mc_addr,
138 				      &mem_info->sys_addr);
139 	if (ret) {
140 		kfree(mem_info);
141 		return NULL;
142 	}
143 
144 	return mem_info;
145 }
146 
147 static void isp4if_gpu_mem_free(struct isp4_interface *ispif,
148 				struct isp4if_gpu_mem_info **mem_info_ptr)
149 {
150 	struct isp4if_gpu_mem_info *mem_info = *mem_info_ptr;
151 	struct device *dev = ispif->dev;
152 
153 	if (!mem_info) {
154 		dev_err(dev, "invalid mem_info\n");
155 		return;
156 	}
157 
158 	*mem_info_ptr = NULL;
159 	isp_kernel_buffer_free(&mem_info->mem_handle, &mem_info->gpu_mc_addr,
160 			       &mem_info->sys_addr);
161 	kfree(mem_info);
162 }
163 
164 static void isp4if_dealloc_fw_gpumem(struct isp4_interface *ispif)
165 {
166 	isp4if_gpu_mem_free(ispif, &ispif->fw_mem_pool);
167 	isp4if_gpu_mem_free(ispif, &ispif->fw_cmd_resp_buf);
168 	isp4if_gpu_mem_free(ispif, &ispif->fw_log_buf);
169 
170 	for (unsigned int i = 0; i < ISP4IF_MAX_STREAM_BUF_COUNT; i++)
171 		isp4if_gpu_mem_free(ispif, &ispif->meta_info_buf[i]);
172 }
173 
174 static int isp4if_alloc_fw_gpumem(struct isp4_interface *ispif)
175 {
176 	struct device *dev = ispif->dev;
177 
178 	ispif->fw_mem_pool = isp4if_gpu_mem_alloc(ispif,
179 						  ISP4FW_MEMORY_POOL_SIZE);
180 	if (!ispif->fw_mem_pool)
181 		goto error_no_memory;
182 
183 	ispif->fw_cmd_resp_buf =
184 		isp4if_gpu_mem_alloc(ispif, ISP4IF_RB_PMBMAP_MEM_SIZE);
185 	if (!ispif->fw_cmd_resp_buf)
186 		goto error_no_memory;
187 
188 	ispif->fw_log_buf =
189 		isp4if_gpu_mem_alloc(ispif, ISP4IF_FW_LOG_RINGBUF_SIZE);
190 	if (!ispif->fw_log_buf)
191 		goto error_no_memory;
192 
193 	for (unsigned int i = 0; i < ISP4IF_MAX_STREAM_BUF_COUNT; i++) {
194 		ispif->meta_info_buf[i] =
195 			isp4if_gpu_mem_alloc(ispif, ISP4IF_META_INFO_BUF_SIZE);
196 		if (!ispif->meta_info_buf[i])
197 			goto error_no_memory;
198 	}
199 
200 	return 0;
201 
202 error_no_memory:
203 	dev_err(dev, "failed to allocate gpu memory\n");
204 	return -ENOMEM;
205 }
206 
207 static u32 isp4if_compute_check_sum(const void *buf, size_t buf_size)
208 {
209 	const u8 *surplus_ptr;
210 	const u32 *buffer;
211 	u32 checksum = 0;
212 	size_t i;
213 
214 	buffer = (const u32 *)buf;
215 	for (i = 0; i < buf_size / sizeof(u32); i++)
216 		checksum += buffer[i];
217 
218 	surplus_ptr = (const u8 *)&buffer[i];
219 	/* add surplus data crc checksum */
220 	for (i = 0; i < buf_size % sizeof(u32); i++)
221 		checksum += surplus_ptr[i];
222 
223 	return checksum;
224 }
225 
226 void isp4if_clear_cmdq(struct isp4_interface *ispif)
227 {
228 	struct isp4if_cmd_element *buf_node, *tmp_node;
229 	LIST_HEAD(free_list);
230 
231 	scoped_guard(spinlock, &ispif->cmdq_lock)
232 		list_splice_init(&ispif->cmdq, &free_list);
233 
234 	list_for_each_entry_safe(buf_node, tmp_node, &free_list, list)
235 		kfree(buf_node);
236 }
237 
238 static bool isp4if_is_cmdq_rb_full(struct isp4_interface *ispif,
239 				   enum isp4if_stream_id stream)
240 {
241 	struct isp4if_rb_config *rb_config = &isp4if_cmd_rb_config[stream];
242 	u32 rreg = rb_config->reg_rptr, wreg = rb_config->reg_wptr;
243 	u32 len = rb_config->val_size;
244 	u32 rd_ptr, wr_ptr;
245 	u32 bytes_free;
246 
247 	rd_ptr = isp4hw_rreg(ispif->mmio, rreg);
248 	wr_ptr = isp4hw_rreg(ispif->mmio, wreg);
249 
250 	/*
251 	 * Read and write pointers are equal, indicating the ring buffer
252 	 * is empty
253 	 */
254 	if (wr_ptr == rd_ptr)
255 		return false;
256 
257 	if (wr_ptr > rd_ptr)
258 		bytes_free = len - (wr_ptr - rd_ptr);
259 	else
260 		bytes_free = rd_ptr - wr_ptr;
261 
262 	/*
263 	 * Ignore one byte from the bytes free to prevent rd_ptr from equaling
264 	 * wr_ptr when the ring buffer is full, because rd_ptr == wr_ptr is
265 	 * supposed to indicate that the ring buffer is empty.
266 	 */
267 	return bytes_free <= sizeof(struct isp4fw_cmd);
268 }
269 
270 struct isp4if_cmd_element *isp4if_rm_cmd_from_cmdq(struct isp4_interface *ispif,
271 						   u32 seq_num, u32 cmd_id)
272 {
273 	struct isp4if_cmd_element *ele;
274 
275 	guard(spinlock)(&ispif->cmdq_lock);
276 
277 	list_for_each_entry(ele, &ispif->cmdq, list) {
278 		if (ele->seq_num == seq_num && ele->cmd_id == cmd_id) {
279 			list_del(&ele->list);
280 			return ele;
281 		}
282 	}
283 
284 	return NULL;
285 }
286 
287 /* Must check that isp4if_is_cmdq_rb_full() == false before calling */
288 static int isp4if_insert_isp_fw_cmd(struct isp4_interface *ispif,
289 				    enum isp4if_stream_id stream,
290 				    const struct isp4fw_cmd *cmd)
291 {
292 	struct isp4if_rb_config *rb_config = &isp4if_cmd_rb_config[stream];
293 	u32 rreg = rb_config->reg_rptr, wreg = rb_config->reg_wptr;
294 	void *mem_sys = rb_config->base_sys_addr;
295 	const u32 cmd_sz = sizeof(*cmd);
296 	struct device *dev = ispif->dev;
297 	u32 len = rb_config->val_size;
298 	const void *src = cmd;
299 	u32 rd_ptr, wr_ptr;
300 	u32 bytes_to_end;
301 
302 	rd_ptr = isp4hw_rreg(ispif->mmio, rreg);
303 	wr_ptr = isp4hw_rreg(ispif->mmio, wreg);
304 	if (rd_ptr >= len || wr_ptr >= len) {
305 		dev_err(dev,
306 			"rb invalid: stream=%u(%s), rd=%u, wr=%u, len=%u, cmd_sz=%u\n",
307 			stream, isp4dbg_get_if_stream_str(stream), rd_ptr,
308 			wr_ptr, len, cmd_sz);
309 		return -EINVAL;
310 	}
311 
312 	bytes_to_end = len - wr_ptr;
313 	if (bytes_to_end >= cmd_sz) {
314 		/* FW cmd is just a straight copy to the write pointer */
315 		memcpy(mem_sys + wr_ptr, src, cmd_sz);
316 		isp4hw_wreg(ispif->mmio, wreg, (wr_ptr + cmd_sz) % len);
317 	} else {
318 		/*
319 		 * FW cmd is split because the ring buffer needs to wrap
320 		 * around
321 		 */
322 		memcpy(mem_sys + wr_ptr, src, bytes_to_end);
323 		memcpy(mem_sys, src + bytes_to_end, cmd_sz - bytes_to_end);
324 		isp4hw_wreg(ispif->mmio, wreg, cmd_sz - bytes_to_end);
325 	}
326 
327 	return 0;
328 }
329 
330 static inline enum isp4if_stream_id isp4if_get_fw_stream(u32 cmd_id)
331 {
332 	return ISP4IF_STREAM_ID_1;
333 }
334 
335 static int isp4if_send_fw_cmd(struct isp4_interface *ispif, u32 cmd_id,
336 			      const void *package,
337 			      u32 package_size, bool sync)
338 {
339 	enum isp4if_stream_id stream = isp4if_get_fw_stream(cmd_id);
340 	struct isp4if_cmd_element *ele = NULL;
341 	struct device *dev = ispif->dev;
342 	struct isp4fw_cmd cmd;
343 	u32 seq_num;
344 	int ret;
345 
346 	if (package_size > sizeof(cmd.cmd_param)) {
347 		dev_err(dev, "fail pkgsize(%u) > %zu cmd:0x%x, stream %d\n",
348 			package_size, sizeof(cmd.cmd_param), cmd_id, stream);
349 		return -EINVAL;
350 	}
351 
352 	/*
353 	 * The struct will be shared with ISP FW, use memset() to guarantee
354 	 * padding bits are zeroed, since this is not guaranteed on all
355 	 * compilers.
356 	 */
357 	memset(&cmd, 0, sizeof(cmd));
358 	cmd.cmd_id = cmd_id;
359 	switch (stream) {
360 	case ISP4IF_STREAM_ID_GLOBAL:
361 		cmd.cmd_stream_id = ISP4FW_STREAM_ID_INVALID;
362 		break;
363 	case ISP4IF_STREAM_ID_1:
364 		cmd.cmd_stream_id = ISP4FW_STREAM_ID_1;
365 		break;
366 	default:
367 		dev_err(dev, "fail bad stream id %d\n", stream);
368 		return -EINVAL;
369 	}
370 
371 	/* Allocate the sync command object early and outside of the lock */
372 	if (sync) {
373 		ele = kmalloc_obj(*ele, GFP_KERNEL);
374 		if (!ele)
375 			return -ENOMEM;
376 
377 		/* Get two references: one for the resp thread, one for us */
378 		atomic_set(&ele->refcnt, 2);
379 		init_completion(&ele->cmd_done);
380 	}
381 
382 	if (package && package_size)
383 		memcpy(cmd.cmd_param, package, package_size);
384 
385 	scoped_guard(mutex, &ispif->isp4if_mutex) {
386 		ret = read_poll_timeout(isp4if_is_cmdq_rb_full, ret, !ret,
387 					ISP4IF_RB_FULL_SLEEP_US,
388 					ISP4IF_RB_FULL_TIMEOUT_US, false, ispif,
389 					stream);
390 		if (ret) {
391 			struct isp4if_rb_config *rb_config =
392 					&isp4if_resp_rb_config[stream];
393 			u32 rd_ptr = isp4hw_rreg(ispif->mmio,
394 						 rb_config->reg_rptr);
395 			u32 wr_ptr = isp4hw_rreg(ispif->mmio,
396 						 rb_config->reg_wptr);
397 
398 			dev_err(dev,
399 				"failed to get free cmdq slot, stream %s(%d),rd %u, wr %u\n",
400 				isp4dbg_get_if_stream_str(stream), stream,
401 				rd_ptr, wr_ptr);
402 			ret = -ETIMEDOUT;
403 			goto free_ele;
404 		}
405 
406 		seq_num = ispif->host2fw_seq_num++;
407 		cmd.cmd_seq_num = seq_num;
408 		cmd.cmd_check_sum = isp4if_compute_check_sum(&cmd, sizeof(cmd)
409 							     - sizeof(u32));
410 
411 		/*
412 		 * only append the fw cmd to queue when its response needs to
413 		 * be waited for, currently there are only two such commands,
414 		 * disable channel and stop stream which are only sent after
415 		 * close camera
416 		 */
417 		if (ele) {
418 			ele->seq_num = seq_num;
419 			ele->cmd_id = cmd_id;
420 			scoped_guard(spinlock, &ispif->cmdq_lock)
421 				list_add_tail(&ele->list, &ispif->cmdq);
422 		}
423 
424 		ret = isp4if_insert_isp_fw_cmd(ispif, stream, &cmd);
425 		if (ret) {
426 			dev_err(dev,
427 				"fail for insert_isp_fw_cmd cmd_id %s(0x%08x)\n",
428 				isp4dbg_get_cmd_str(cmd_id), cmd_id);
429 			goto err_dequeue_ele;
430 		}
431 	}
432 
433 	if (ele) {
434 		ret = wait_for_completion_timeout(&ele->cmd_done,
435 						  ISP4IF_FW_CMD_TIMEOUT);
436 		if (!ret) {
437 			ret = -ETIMEDOUT;
438 			goto err_dequeue_ele;
439 		}
440 
441 		ret = 0;
442 		goto put_ele_ref;
443 	}
444 
445 	return 0;
446 
447 err_dequeue_ele:
448 	/*
449 	 * Try to remove the command from the queue. If that fails, then it
450 	 * means the response thread is currently using the object, and we need
451 	 * to use the refcount to avoid a use-after-free by either side.
452 	 */
453 	if (ele && isp4if_rm_cmd_from_cmdq(ispif, seq_num, cmd_id))
454 		goto free_ele;
455 
456 put_ele_ref:
457 	/* Don't free the command if we didn't put the last reference */
458 	if (ele && atomic_dec_return(&ele->refcnt))
459 		ele = NULL;
460 
461 free_ele:
462 	kfree(ele);
463 	return ret;
464 }
465 
466 static int isp4if_send_buffer(struct isp4_interface *ispif,
467 			      struct isp4if_img_buf_info *buf_info)
468 {
469 	struct isp4fw_cmd_send_buffer cmd;
470 
471 	/*
472 	 * The struct will be shared with ISP FW, use memset() to guarantee
473 	 * padding bits are zeroed, since this is not guaranteed on all
474 	 * compilers.
475 	 */
476 	memset(&cmd, 0, sizeof(cmd));
477 	cmd.buffer_type = ISP4FW_BUFFER_TYPE_PREVIEW;
478 	cmd.buffer.vmid_space.bit.space = ISP4FW_ADDR_SPACE_TYPE_GPU_VA;
479 	isp4if_split_addr64(buf_info->planes[0].mc_addr,
480 			    &cmd.buffer.buf_base_a_lo,
481 			    &cmd.buffer.buf_base_a_hi);
482 	cmd.buffer.buf_size_a = buf_info->planes[0].len;
483 
484 	isp4if_split_addr64(buf_info->planes[1].mc_addr,
485 			    &cmd.buffer.buf_base_b_lo,
486 			    &cmd.buffer.buf_base_b_hi);
487 	cmd.buffer.buf_size_b = buf_info->planes[1].len;
488 
489 	isp4if_split_addr64(buf_info->planes[2].mc_addr,
490 			    &cmd.buffer.buf_base_c_lo,
491 			    &cmd.buffer.buf_base_c_hi);
492 	cmd.buffer.buf_size_c = buf_info->planes[2].len;
493 
494 	return isp4if_send_fw_cmd(ispif, ISP4FW_CMD_ID_SEND_BUFFER, &cmd,
495 				  sizeof(cmd), false);
496 }
497 
498 static void isp4if_init_rb_config(struct isp4_interface *ispif,
499 				  struct isp4if_rb_config *rb_config)
500 {
501 	isp4hw_wreg(ispif->mmio, rb_config->reg_rptr, 0x0);
502 	isp4hw_wreg(ispif->mmio, rb_config->reg_wptr, 0x0);
503 	isp4hw_wreg(ispif->mmio, rb_config->reg_base_lo,
504 		    rb_config->base_mc_addr);
505 	isp4hw_wreg(ispif->mmio, rb_config->reg_base_hi,
506 		    rb_config->base_mc_addr >> 32);
507 	isp4hw_wreg(ispif->mmio, rb_config->reg_size, rb_config->val_size);
508 }
509 
510 static int isp4if_fw_init(struct isp4_interface *ispif)
511 {
512 	u32 aligned_rb_chunk_size = ISP4IF_RB_PMBMAP_MEM_CHUNK & 0xffffffc0;
513 	struct isp4if_rb_config *rb_config;
514 	u32 offset;
515 	unsigned int i;
516 
517 	/* initialize CMD_RB streams */
518 	for (i = 0; i < ISP4IF_STREAM_ID_MAX; i++) {
519 		rb_config = (isp4if_cmd_rb_config + i);
520 		offset = aligned_rb_chunk_size * rb_config->index;
521 
522 		rb_config->val_size = ISP4IF_FW_CMD_BUF_SIZE;
523 		rb_config->base_sys_addr =
524 			ispif->fw_cmd_resp_buf->sys_addr + offset;
525 		rb_config->base_mc_addr =
526 			ispif->fw_cmd_resp_buf->gpu_mc_addr + offset;
527 
528 		isp4if_init_rb_config(ispif, rb_config);
529 	}
530 
531 	/* initialize RESP_RB streams */
532 	for (i = 0; i < ISP4IF_STREAM_ID_MAX; i++) {
533 		rb_config = (isp4if_resp_rb_config + i);
534 		offset = aligned_rb_chunk_size *
535 			 (rb_config->index + ISP4IF_RESP_CHAN_TO_RB_OFFSET - 1);
536 
537 		rb_config->val_size = ISP4IF_FW_CMD_BUF_SIZE;
538 		rb_config->base_sys_addr =
539 			ispif->fw_cmd_resp_buf->sys_addr + offset;
540 		rb_config->base_mc_addr =
541 			ispif->fw_cmd_resp_buf->gpu_mc_addr + offset;
542 
543 		isp4if_init_rb_config(ispif, rb_config);
544 	}
545 
546 	/* initialize LOG_RB stream */
547 	rb_config = &isp4if_log_rb_config;
548 	rb_config->val_size = ISP4IF_FW_LOG_RINGBUF_SIZE;
549 	rb_config->base_mc_addr = ispif->fw_log_buf->gpu_mc_addr;
550 	rb_config->base_sys_addr = ispif->fw_log_buf->sys_addr;
551 
552 	isp4if_init_rb_config(ispif, rb_config);
553 
554 	return 0;
555 }
556 
557 static int isp4if_wait_fw_ready(struct isp4_interface *ispif,
558 				u32 isp_status_addr)
559 {
560 	struct device *dev = ispif->dev;
561 	u32 timeout_ms = 100;
562 	u32 interval_ms = 1;
563 	u32 reg_val;
564 
565 	/* wait for FW initialize done! */
566 	if (!read_poll_timeout(isp4hw_rreg, reg_val, reg_val
567 			       & ISP_STATUS__CCPU_REPORT_MASK,
568 			       interval_ms * 1000, timeout_ms * 1000, false,
569 			       ispif->mmio, isp_status_addr))
570 		return 0;
571 
572 	dev_err(dev, "ISP CCPU FW boot failed\n");
573 
574 	return -ETIME;
575 }
576 
577 static void isp4if_enable_ccpu(struct isp4_interface *ispif)
578 {
579 	u32 reg_val;
580 
581 	reg_val = isp4hw_rreg(ispif->mmio, ISP_SOFT_RESET);
582 	reg_val &= (~ISP_SOFT_RESET__CCPU_SOFT_RESET_MASK);
583 	isp4hw_wreg(ispif->mmio, ISP_SOFT_RESET, reg_val);
584 
585 	usleep_range(100, 150);
586 
587 	reg_val = isp4hw_rreg(ispif->mmio, ISP_CCPU_CNTL);
588 	reg_val &= (~ISP_CCPU_CNTL__CCPU_HOST_SOFT_RST_MASK);
589 	isp4hw_wreg(ispif->mmio, ISP_CCPU_CNTL, reg_val);
590 }
591 
592 static void isp4if_disable_ccpu(struct isp4_interface *ispif)
593 {
594 	u32 reg_val;
595 
596 	reg_val = isp4hw_rreg(ispif->mmio, ISP_CCPU_CNTL);
597 	reg_val |= ISP_CCPU_CNTL__CCPU_HOST_SOFT_RST_MASK;
598 	isp4hw_wreg(ispif->mmio, ISP_CCPU_CNTL, reg_val);
599 
600 	usleep_range(100, 150);
601 
602 	reg_val = isp4hw_rreg(ispif->mmio, ISP_SOFT_RESET);
603 	reg_val |= ISP_SOFT_RESET__CCPU_SOFT_RESET_MASK;
604 	isp4hw_wreg(ispif->mmio, ISP_SOFT_RESET, reg_val);
605 }
606 
607 static int isp4if_fw_boot(struct isp4_interface *ispif)
608 {
609 	struct device *dev = ispif->dev;
610 
611 	if (ispif->status != ISP4IF_STATUS_PWR_ON) {
612 		dev_err(dev, "invalid isp power status %d\n", ispif->status);
613 		return -EINVAL;
614 	}
615 
616 	isp4if_disable_ccpu(ispif);
617 
618 	isp4if_fw_init(ispif);
619 
620 	/* clear ccpu status */
621 	isp4hw_wreg(ispif->mmio, ISP_STATUS, 0x0);
622 
623 	isp4if_enable_ccpu(ispif);
624 
625 	if (isp4if_wait_fw_ready(ispif, ISP_STATUS)) {
626 		isp4if_disable_ccpu(ispif);
627 		return -EINVAL;
628 	}
629 
630 	/* enable interrupts */
631 	isp4hw_wreg(ispif->mmio, ISP_SYS_INT0_EN,
632 		    ISP4IF_FW_RESP_RB_IRQ_EN_MASK);
633 
634 	ispif->status = ISP4IF_STATUS_FW_RUNNING;
635 
636 	dev_dbg(dev, "ISP CCPU FW boot success\n");
637 
638 	return 0;
639 }
640 
641 int isp4if_f2h_resp(struct isp4_interface *ispif, enum isp4if_stream_id stream,
642 		    struct isp4fw_resp *resp)
643 {
644 	struct isp4if_rb_config *rb_config = &isp4if_resp_rb_config[stream];
645 	u32 rreg = rb_config->reg_rptr, wreg = rb_config->reg_wptr;
646 	void *mem_sys = rb_config->base_sys_addr;
647 	const u32 resp_sz = sizeof(*resp);
648 	struct device *dev = ispif->dev;
649 	u32 len = rb_config->val_size;
650 	u32 rd_ptr, wr_ptr;
651 	u32 bytes_to_end;
652 	void *dst = resp;
653 	u32 checksum;
654 
655 	rd_ptr = isp4hw_rreg(ispif->mmio, rreg);
656 	wr_ptr = isp4hw_rreg(ispif->mmio, wreg);
657 	if (rd_ptr >= len || wr_ptr >= len)
658 		goto err_rb_invalid;
659 
660 	/*
661 	 * Read and write pointers are equal, indicating the ring buffer is
662 	 * empty
663 	 */
664 	if (rd_ptr == wr_ptr)
665 		return -ENODATA;
666 
667 	bytes_to_end = len - rd_ptr;
668 	if (bytes_to_end >= resp_sz) {
669 		/* FW response is just a straight copy from the read pointer */
670 		if (wr_ptr > rd_ptr && wr_ptr - rd_ptr < resp_sz)
671 			goto err_rb_invalid;
672 
673 		memcpy(dst, mem_sys + rd_ptr, resp_sz);
674 		isp4hw_wreg(ispif->mmio, rreg, (rd_ptr + resp_sz) % len);
675 	} else {
676 		/*
677 		 * FW response is split because the ring buffer wrapped
678 		 * around
679 		 */
680 		if (wr_ptr > rd_ptr || wr_ptr < resp_sz - bytes_to_end)
681 			goto err_rb_invalid;
682 
683 		memcpy(dst, mem_sys + rd_ptr, bytes_to_end);
684 		memcpy(dst + bytes_to_end, mem_sys, resp_sz - bytes_to_end);
685 		isp4hw_wreg(ispif->mmio, rreg, resp_sz - bytes_to_end);
686 	}
687 
688 	checksum = isp4if_compute_check_sum(resp, resp_sz - sizeof(u32));
689 	if (checksum != resp->resp_check_sum) {
690 		dev_err(dev, "resp checksum 0x%x,should 0x%x,rptr %u,wptr %u\n",
691 			checksum, resp->resp_check_sum, rd_ptr, wr_ptr);
692 		dev_err(dev, "%s(%u), seqNo %u, resp_id %s(0x%x)\n",
693 			isp4dbg_get_if_stream_str(stream), stream,
694 			resp->resp_seq_num, isp4dbg_get_resp_str(resp->resp_id),
695 			resp->resp_id);
696 		return -EINVAL;
697 	}
698 
699 	return 0;
700 
701 err_rb_invalid:
702 	dev_err(dev,
703 		"rb invalid: stream=%u(%s), rd=%u, wr=%u, len=%u, resp_sz=%u\n",
704 		stream, isp4dbg_get_if_stream_str(stream), rd_ptr, wr_ptr, len,
705 		resp_sz);
706 	return -EINVAL;
707 }
708 
709 int isp4if_send_command(struct isp4_interface *ispif, u32 cmd_id,
710 			const void *package, u32 package_size)
711 {
712 	return isp4if_send_fw_cmd(ispif, cmd_id, package, package_size, false);
713 }
714 
715 int isp4if_send_command_sync(struct isp4_interface *ispif, u32 cmd_id,
716 			     const void *package, u32 package_size)
717 {
718 	return isp4if_send_fw_cmd(ispif, cmd_id, package, package_size, true);
719 }
720 
721 void isp4if_clear_bufq(struct isp4_interface *ispif)
722 {
723 	struct isp4if_img_buf_node *buf_node, *tmp_node;
724 	LIST_HEAD(free_list);
725 
726 	scoped_guard(spinlock, &ispif->bufq_lock)
727 		list_splice_init(&ispif->bufq, &free_list);
728 
729 	list_for_each_entry_safe(buf_node, tmp_node, &free_list, node)
730 		kfree(buf_node);
731 }
732 
733 void isp4if_dealloc_buffer_node(struct isp4if_img_buf_node *buf_node)
734 {
735 	kfree(buf_node);
736 }
737 
738 struct isp4if_img_buf_node *
739 isp4if_alloc_buffer_node(struct isp4if_img_buf_info *buf_info)
740 {
741 	struct isp4if_img_buf_node *node;
742 
743 	node = kmalloc_obj(*node, GFP_KERNEL);
744 	if (node)
745 		node->buf_info = *buf_info;
746 
747 	return node;
748 }
749 
750 struct isp4if_img_buf_node *isp4if_dequeue_buffer(struct isp4_interface *ispif)
751 {
752 	struct isp4if_img_buf_node *buf_node;
753 
754 	guard(spinlock)(&ispif->bufq_lock);
755 
756 	buf_node = list_first_entry_or_null(&ispif->bufq, typeof(*buf_node),
757 					    node);
758 	if (buf_node)
759 		list_del(&buf_node->node);
760 
761 	return buf_node;
762 }
763 
764 int isp4if_queue_buffer(struct isp4_interface *ispif,
765 			struct isp4if_img_buf_node *buf_node)
766 {
767 	int ret;
768 
769 	ret = isp4if_send_buffer(ispif, &buf_node->buf_info);
770 	if (ret)
771 		return ret;
772 
773 	scoped_guard(spinlock, &ispif->bufq_lock)
774 		list_add_tail(&buf_node->node, &ispif->bufq);
775 
776 	return 0;
777 }
778 
779 int isp4if_stop(struct isp4_interface *ispif)
780 {
781 	isp4if_disable_ccpu(ispif);
782 
783 	isp4if_dealloc_fw_gpumem(ispif);
784 
785 	return 0;
786 }
787 
788 int isp4if_start(struct isp4_interface *ispif)
789 {
790 	int ret;
791 
792 	ret = isp4if_alloc_fw_gpumem(ispif);
793 	if (ret)
794 		return ret;
795 
796 	ret = isp4if_fw_boot(ispif);
797 	if (ret)
798 		goto failed_fw_boot;
799 
800 	return 0;
801 
802 failed_fw_boot:
803 	isp4if_dealloc_fw_gpumem(ispif);
804 	return ret;
805 }
806 
807 int isp4if_deinit(struct isp4_interface *ispif)
808 {
809 	isp4if_clear_cmdq(ispif);
810 
811 	isp4if_clear_bufq(ispif);
812 
813 	mutex_destroy(&ispif->isp4if_mutex);
814 
815 	return 0;
816 }
817 
818 int isp4if_init(struct isp4_interface *ispif, struct device *dev,
819 		void __iomem *isp_mmio)
820 {
821 	ispif->dev = dev;
822 	ispif->mmio = isp_mmio;
823 
824 	spin_lock_init(&ispif->cmdq_lock); /* used for cmdq access */
825 	spin_lock_init(&ispif->bufq_lock); /* used for bufq access */
826 	mutex_init(&ispif->isp4if_mutex); /* used for commands sent to ispfw */
827 
828 	INIT_LIST_HEAD(&ispif->cmdq);
829 	INIT_LIST_HEAD(&ispif->bufq);
830 
831 	return 0;
832 }
833