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