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 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 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 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 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 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 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 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 */ 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 328 static inline enum isp4if_stream_id isp4if_get_fw_stream(u32 cmd_id) 329 { 330 return ISP4IF_STREAM_ID_1; 331 } 332 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, GFP_KERNEL); 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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, GFP_KERNEL); 742 if (node) 743 node->buf_info = *buf_info; 744 745 return node; 746 } 747 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 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 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 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 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 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