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