1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2013--2024 Intel Corporation 4 */ 5 6 #include <linux/cacheflush.h> 7 #include <linux/delay.h> 8 #include <linux/device.h> 9 #include <linux/io.h> 10 #include <linux/spinlock.h> 11 #include <linux/types.h> 12 13 #include "ipu6-bus.h" 14 #include "ipu6-fw-com.h" 15 #include "ipu6-isys.h" 16 #include "ipu6-platform-isys-csi2-reg.h" 17 #include "ipu6-platform-regs.h" 18 19 static const char send_msg_types[N_IPU6_FW_ISYS_SEND_TYPE][32] = { 20 "STREAM_OPEN", 21 "STREAM_START", 22 "STREAM_START_AND_CAPTURE", 23 "STREAM_CAPTURE", 24 "STREAM_STOP", 25 "STREAM_FLUSH", 26 "STREAM_CLOSE" 27 }; 28 29 static int handle_proxy_response(struct ipu6_isys *isys, unsigned int req_id) 30 { 31 struct device *dev = &isys->adev->auxdev.dev; 32 struct ipu6_fw_isys_proxy_resp_info_abi *resp; 33 int ret; 34 35 resp = ipu6_recv_get_token(isys->fwcom, IPU6_BASE_PROXY_RECV_QUEUES); 36 if (!resp) 37 return 1; 38 39 dev_dbg(dev, "Proxy response: id %u, error %u, details %u\n", 40 resp->request_id, resp->error_info.error, 41 resp->error_info.error_details); 42 43 ret = req_id == resp->request_id ? 0 : -EIO; 44 45 ipu6_recv_put_token(isys->fwcom, IPU6_BASE_PROXY_RECV_QUEUES); 46 47 return ret; 48 } 49 50 int ipu6_fw_isys_send_proxy_token(struct ipu6_isys *isys, 51 unsigned int req_id, 52 unsigned int index, 53 unsigned int offset, u32 value) 54 { 55 struct ipu6_fw_com_context *ctx = isys->fwcom; 56 struct device *dev = &isys->adev->auxdev.dev; 57 struct ipu6_fw_proxy_send_queue_token *token; 58 unsigned int timeout = 1000; 59 int ret; 60 61 dev_dbg(dev, 62 "proxy send: req_id 0x%x, index %d, offset 0x%x, value 0x%x\n", 63 req_id, index, offset, value); 64 65 token = ipu6_send_get_token(ctx, IPU6_BASE_PROXY_SEND_QUEUES); 66 if (!token) 67 return -EBUSY; 68 69 token->request_id = req_id; 70 token->region_index = index; 71 token->offset = offset; 72 token->value = value; 73 ipu6_send_put_token(ctx, IPU6_BASE_PROXY_SEND_QUEUES); 74 75 do { 76 usleep_range(100, 110); 77 ret = handle_proxy_response(isys, req_id); 78 if (!ret) 79 break; 80 if (ret == -EIO) { 81 dev_err(dev, "Proxy respond with unexpected id\n"); 82 break; 83 } 84 timeout--; 85 } while (ret && timeout); 86 87 if (!timeout) 88 dev_err(dev, "Proxy response timed out\n"); 89 90 return ret; 91 } 92 93 int ipu6_fw_isys_complex_cmd(struct ipu6_isys *isys, 94 const unsigned int stream_handle, 95 void *cpu_mapped_buf, 96 dma_addr_t dma_mapped_buf, 97 size_t size, u16 send_type) 98 { 99 struct ipu6_fw_com_context *ctx = isys->fwcom; 100 struct device *dev = &isys->adev->auxdev.dev; 101 struct ipu6_fw_send_queue_token *token; 102 103 if (send_type >= N_IPU6_FW_ISYS_SEND_TYPE) 104 return -EINVAL; 105 106 dev_dbg(dev, "send_token: %s\n", send_msg_types[send_type]); 107 108 /* 109 * Time to flush cache in case we have some payload. Not all messages 110 * have that 111 */ 112 if (cpu_mapped_buf) 113 clflush_cache_range(cpu_mapped_buf, size); 114 115 token = ipu6_send_get_token(ctx, 116 stream_handle + IPU6_BASE_MSG_SEND_QUEUES); 117 if (!token) 118 return -EBUSY; 119 120 token->payload = dma_mapped_buf; 121 token->buf_handle = (unsigned long)cpu_mapped_buf; 122 token->send_type = send_type; 123 124 ipu6_send_put_token(ctx, stream_handle + IPU6_BASE_MSG_SEND_QUEUES); 125 126 return 0; 127 } 128 129 int ipu6_fw_isys_simple_cmd(struct ipu6_isys *isys, 130 const unsigned int stream_handle, u16 send_type) 131 { 132 return ipu6_fw_isys_complex_cmd(isys, stream_handle, NULL, 0, 0, 133 send_type); 134 } 135 136 int ipu6_fw_isys_close(struct ipu6_isys *isys) 137 { 138 struct device *dev = &isys->adev->auxdev.dev; 139 int retry = IPU6_ISYS_CLOSE_RETRY; 140 unsigned long flags; 141 void *fwcom; 142 int ret; 143 144 /* 145 * Stop the isys fw. Actual close takes 146 * some time as the FW must stop its actions including code fetch 147 * to SP icache. 148 * spinlock to wait the interrupt handler to be finished 149 */ 150 spin_lock_irqsave(&isys->power_lock, flags); 151 ret = ipu6_fw_com_close(isys->fwcom); 152 fwcom = isys->fwcom; 153 isys->fwcom = NULL; 154 spin_unlock_irqrestore(&isys->power_lock, flags); 155 if (ret) 156 dev_err(dev, "Device close failure: %d\n", ret); 157 158 /* release probably fails if the close failed. Let's try still */ 159 do { 160 usleep_range(400, 500); 161 ret = ipu6_fw_com_release(fwcom, 0); 162 retry--; 163 } while (ret && retry); 164 165 if (ret) { 166 dev_err(dev, "Device release time out %d\n", ret); 167 spin_lock_irqsave(&isys->power_lock, flags); 168 isys->fwcom = fwcom; 169 spin_unlock_irqrestore(&isys->power_lock, flags); 170 } 171 172 return ret; 173 } 174 175 void ipu6_fw_isys_cleanup(struct ipu6_isys *isys) 176 { 177 int ret; 178 179 ret = ipu6_fw_com_release(isys->fwcom, 1); 180 if (ret < 0) 181 dev_warn(&isys->adev->auxdev.dev, 182 "Device busy, fw_com release failed."); 183 isys->fwcom = NULL; 184 } 185 186 static void start_sp(struct ipu6_bus_device *adev) 187 { 188 struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev); 189 void __iomem *spc_regs_base = isys->pdata->base + 190 isys->pdata->ipdata->hw_variant.spc_offset; 191 u32 val = IPU6_ISYS_SPC_STATUS_START | 192 IPU6_ISYS_SPC_STATUS_RUN | 193 IPU6_ISYS_SPC_STATUS_CTRL_ICACHE_INVALIDATE; 194 195 val |= isys->icache_prefetch ? IPU6_ISYS_SPC_STATUS_ICACHE_PREFETCH : 0; 196 197 writel(val, spc_regs_base + IPU6_ISYS_REG_SPC_STATUS_CTRL); 198 } 199 200 static int query_sp(struct ipu6_bus_device *adev) 201 { 202 struct ipu6_isys *isys = ipu6_bus_get_drvdata(adev); 203 void __iomem *spc_regs_base = isys->pdata->base + 204 isys->pdata->ipdata->hw_variant.spc_offset; 205 u32 val; 206 207 val = readl(spc_regs_base + IPU6_ISYS_REG_SPC_STATUS_CTRL); 208 /* return true when READY == 1, START == 0 */ 209 val &= IPU6_ISYS_SPC_STATUS_READY | IPU6_ISYS_SPC_STATUS_START; 210 211 return val == IPU6_ISYS_SPC_STATUS_READY; 212 } 213 214 static int ipu6_isys_fwcom_cfg_init(struct ipu6_isys *isys, 215 struct ipu6_fw_com_cfg *fwcom, 216 unsigned int num_streams) 217 { 218 unsigned int max_send_queues, max_sram_blocks, max_devq_size; 219 struct ipu6_fw_syscom_queue_config *input_queue_cfg; 220 struct ipu6_fw_syscom_queue_config *output_queue_cfg; 221 struct device *dev = &isys->adev->auxdev.dev; 222 int type_proxy = IPU6_FW_ISYS_QUEUE_TYPE_PROXY; 223 int type_dev = IPU6_FW_ISYS_QUEUE_TYPE_DEV; 224 int type_msg = IPU6_FW_ISYS_QUEUE_TYPE_MSG; 225 int base_dev_send = IPU6_BASE_DEV_SEND_QUEUES; 226 int base_msg_send = IPU6_BASE_MSG_SEND_QUEUES; 227 int base_msg_recv = IPU6_BASE_MSG_RECV_QUEUES; 228 struct ipu6_fw_isys_fw_config *isys_fw_cfg; 229 u32 num_in_message_queues; 230 unsigned int max_streams; 231 unsigned int size; 232 unsigned int i; 233 234 max_streams = isys->pdata->ipdata->max_streams; 235 max_send_queues = isys->pdata->ipdata->max_send_queues; 236 max_sram_blocks = isys->pdata->ipdata->max_sram_blocks; 237 max_devq_size = isys->pdata->ipdata->max_devq_size; 238 num_in_message_queues = clamp(num_streams, 1U, max_streams); 239 isys_fw_cfg = devm_kzalloc(dev, sizeof(*isys_fw_cfg), GFP_KERNEL); 240 if (!isys_fw_cfg) 241 return -ENOMEM; 242 243 isys_fw_cfg->num_send_queues[type_proxy] = IPU6_N_MAX_PROXY_SEND_QUEUES; 244 isys_fw_cfg->num_send_queues[type_dev] = IPU6_N_MAX_DEV_SEND_QUEUES; 245 isys_fw_cfg->num_send_queues[type_msg] = num_in_message_queues; 246 isys_fw_cfg->num_recv_queues[type_proxy] = IPU6_N_MAX_PROXY_RECV_QUEUES; 247 /* Common msg/dev return queue */ 248 isys_fw_cfg->num_recv_queues[type_dev] = 0; 249 isys_fw_cfg->num_recv_queues[type_msg] = 1; 250 251 size = sizeof(*input_queue_cfg) * max_send_queues; 252 input_queue_cfg = devm_kzalloc(dev, size, GFP_KERNEL); 253 if (!input_queue_cfg) 254 return -ENOMEM; 255 256 size = sizeof(*output_queue_cfg) * IPU6_N_MAX_RECV_QUEUES; 257 output_queue_cfg = devm_kzalloc(dev, size, GFP_KERNEL); 258 if (!output_queue_cfg) 259 return -ENOMEM; 260 261 fwcom->input = input_queue_cfg; 262 fwcom->output = output_queue_cfg; 263 264 fwcom->num_input_queues = isys_fw_cfg->num_send_queues[type_proxy] + 265 isys_fw_cfg->num_send_queues[type_dev] + 266 isys_fw_cfg->num_send_queues[type_msg]; 267 268 fwcom->num_output_queues = isys_fw_cfg->num_recv_queues[type_proxy] + 269 isys_fw_cfg->num_recv_queues[type_dev] + 270 isys_fw_cfg->num_recv_queues[type_msg]; 271 272 /* SRAM partitioning. Equal partitioning is set. */ 273 for (i = 0; i < max_sram_blocks; i++) { 274 if (i < num_in_message_queues) 275 isys_fw_cfg->buffer_partition.num_gda_pages[i] = 276 (IPU6_DEVICE_GDA_NR_PAGES * 277 IPU6_DEVICE_GDA_VIRT_FACTOR) / 278 num_in_message_queues; 279 else 280 isys_fw_cfg->buffer_partition.num_gda_pages[i] = 0; 281 } 282 283 /* FW assumes proxy interface at fwcom queue 0 */ 284 for (i = 0; i < isys_fw_cfg->num_send_queues[type_proxy]; i++) { 285 input_queue_cfg[i].token_size = 286 sizeof(struct ipu6_fw_proxy_send_queue_token); 287 input_queue_cfg[i].queue_size = IPU6_ISYS_SIZE_PROXY_SEND_QUEUE; 288 } 289 290 for (i = 0; i < isys_fw_cfg->num_send_queues[type_dev]; i++) { 291 input_queue_cfg[base_dev_send + i].token_size = 292 sizeof(struct ipu6_fw_send_queue_token); 293 input_queue_cfg[base_dev_send + i].queue_size = max_devq_size; 294 } 295 296 for (i = 0; i < isys_fw_cfg->num_send_queues[type_msg]; i++) { 297 input_queue_cfg[base_msg_send + i].token_size = 298 sizeof(struct ipu6_fw_send_queue_token); 299 input_queue_cfg[base_msg_send + i].queue_size = 300 IPU6_ISYS_SIZE_SEND_QUEUE; 301 } 302 303 for (i = 0; i < isys_fw_cfg->num_recv_queues[type_proxy]; i++) { 304 output_queue_cfg[i].token_size = 305 sizeof(struct ipu6_fw_proxy_resp_queue_token); 306 output_queue_cfg[i].queue_size = 307 IPU6_ISYS_SIZE_PROXY_RECV_QUEUE; 308 } 309 /* There is no recv DEV queue */ 310 for (i = 0; i < isys_fw_cfg->num_recv_queues[type_msg]; i++) { 311 output_queue_cfg[base_msg_recv + i].token_size = 312 sizeof(struct ipu6_fw_resp_queue_token); 313 output_queue_cfg[base_msg_recv + i].queue_size = 314 IPU6_ISYS_SIZE_RECV_QUEUE; 315 } 316 317 fwcom->dmem_addr = isys->pdata->ipdata->hw_variant.dmem_offset; 318 fwcom->specific_addr = isys_fw_cfg; 319 fwcom->specific_size = sizeof(*isys_fw_cfg); 320 321 return 0; 322 } 323 324 int ipu6_fw_isys_init(struct ipu6_isys *isys, unsigned int num_streams) 325 { 326 struct device *dev = &isys->adev->auxdev.dev; 327 int retry = IPU6_ISYS_OPEN_RETRY; 328 struct ipu6_fw_com_cfg fwcom = { 329 .cell_start = start_sp, 330 .cell_ready = query_sp, 331 .buttress_boot_offset = SYSCOM_BUTTRESS_FW_PARAMS_ISYS_OFFSET, 332 }; 333 int ret; 334 335 ipu6_isys_fwcom_cfg_init(isys, &fwcom, num_streams); 336 337 isys->fwcom = ipu6_fw_com_prepare(&fwcom, isys->adev, 338 isys->pdata->base); 339 if (!isys->fwcom) { 340 dev_err(dev, "isys fw com prepare failed\n"); 341 return -EIO; 342 } 343 344 ret = ipu6_fw_com_open(isys->fwcom); 345 if (ret) { 346 dev_err(dev, "isys fw com open failed %d\n", ret); 347 return ret; 348 } 349 350 do { 351 usleep_range(400, 500); 352 if (ipu6_fw_com_ready(isys->fwcom)) 353 break; 354 retry--; 355 } while (retry > 0); 356 357 if (!retry) { 358 dev_err(dev, "isys port open ready failed %d\n", ret); 359 ipu6_fw_isys_close(isys); 360 ret = -EIO; 361 } 362 363 return ret; 364 } 365 366 struct ipu6_fw_isys_resp_info_abi * 367 ipu6_fw_isys_get_resp(void *context, unsigned int queue) 368 { 369 return ipu6_recv_get_token(context, queue); 370 } 371 372 void ipu6_fw_isys_put_resp(void *context, unsigned int queue) 373 { 374 ipu6_recv_put_token(context, queue); 375 } 376 377 void ipu6_fw_isys_dump_stream_cfg(struct device *dev, 378 struct ipu6_fw_isys_stream_cfg_data_abi *cfg) 379 { 380 unsigned int i; 381 382 dev_dbg(dev, "-----------------------------------------------------\n"); 383 dev_dbg(dev, "IPU6_FW_ISYS_STREAM_CFG_DATA\n"); 384 385 dev_dbg(dev, "compfmt = %d\n", cfg->vc); 386 dev_dbg(dev, "src = %d\n", cfg->src); 387 dev_dbg(dev, "vc = %d\n", cfg->vc); 388 dev_dbg(dev, "isl_use = %d\n", cfg->isl_use); 389 dev_dbg(dev, "sensor_type = %d\n", cfg->sensor_type); 390 391 dev_dbg(dev, "send_irq_sof_discarded = %d\n", 392 cfg->send_irq_sof_discarded); 393 dev_dbg(dev, "send_irq_eof_discarded = %d\n", 394 cfg->send_irq_eof_discarded); 395 dev_dbg(dev, "send_resp_sof_discarded = %d\n", 396 cfg->send_resp_sof_discarded); 397 dev_dbg(dev, "send_resp_eof_discarded = %d\n", 398 cfg->send_resp_eof_discarded); 399 400 dev_dbg(dev, "crop:\n"); 401 dev_dbg(dev, "\t.left_top = [%d, %d]\n", cfg->crop.left_offset, 402 cfg->crop.top_offset); 403 dev_dbg(dev, "\t.right_bottom = [%d, %d]\n", cfg->crop.right_offset, 404 cfg->crop.bottom_offset); 405 406 dev_dbg(dev, "nof_input_pins = %d\n", cfg->nof_input_pins); 407 for (i = 0; i < cfg->nof_input_pins; i++) { 408 dev_dbg(dev, "input pin[%d]:\n", i); 409 dev_dbg(dev, "\t.dt = 0x%0x\n", cfg->input_pins[i].dt); 410 dev_dbg(dev, "\t.mipi_store_mode = %d\n", 411 cfg->input_pins[i].mipi_store_mode); 412 dev_dbg(dev, "\t.bits_per_pix = %d\n", 413 cfg->input_pins[i].bits_per_pix); 414 dev_dbg(dev, "\t.mapped_dt = 0x%0x\n", 415 cfg->input_pins[i].mapped_dt); 416 dev_dbg(dev, "\t.input_res = %dx%d\n", 417 cfg->input_pins[i].input_res.width, 418 cfg->input_pins[i].input_res.height); 419 dev_dbg(dev, "\t.mipi_decompression = %d\n", 420 cfg->input_pins[i].mipi_decompression); 421 dev_dbg(dev, "\t.capture_mode = %d\n", 422 cfg->input_pins[i].capture_mode); 423 } 424 425 dev_dbg(dev, "nof_output_pins = %d\n", cfg->nof_output_pins); 426 for (i = 0; i < cfg->nof_output_pins; i++) { 427 dev_dbg(dev, "output_pin[%d]:\n", i); 428 dev_dbg(dev, "\t.input_pin_id = %d\n", 429 cfg->output_pins[i].input_pin_id); 430 dev_dbg(dev, "\t.output_res = %dx%d\n", 431 cfg->output_pins[i].output_res.width, 432 cfg->output_pins[i].output_res.height); 433 dev_dbg(dev, "\t.stride = %d\n", cfg->output_pins[i].stride); 434 dev_dbg(dev, "\t.pt = %d\n", cfg->output_pins[i].pt); 435 dev_dbg(dev, "\t.payload_buf_size = %d\n", 436 cfg->output_pins[i].payload_buf_size); 437 dev_dbg(dev, "\t.ft = %d\n", cfg->output_pins[i].ft); 438 dev_dbg(dev, "\t.watermark_in_lines = %d\n", 439 cfg->output_pins[i].watermark_in_lines); 440 dev_dbg(dev, "\t.send_irq = %d\n", 441 cfg->output_pins[i].send_irq); 442 dev_dbg(dev, "\t.reserve_compression = %d\n", 443 cfg->output_pins[i].reserve_compression); 444 dev_dbg(dev, "\t.snoopable = %d\n", 445 cfg->output_pins[i].snoopable); 446 dev_dbg(dev, "\t.error_handling_enable = %d\n", 447 cfg->output_pins[i].error_handling_enable); 448 dev_dbg(dev, "\t.sensor_type = %d\n", 449 cfg->output_pins[i].sensor_type); 450 } 451 dev_dbg(dev, "-----------------------------------------------------\n"); 452 } 453 454 void 455 ipu6_fw_isys_dump_frame_buff_set(struct device *dev, 456 struct ipu6_fw_isys_frame_buff_set_abi *buf, 457 unsigned int outputs) 458 { 459 unsigned int i; 460 461 dev_dbg(dev, "-----------------------------------------------------\n"); 462 dev_dbg(dev, "IPU6_FW_ISYS_FRAME_BUFF_SET\n"); 463 464 for (i = 0; i < outputs; i++) { 465 dev_dbg(dev, "output_pin[%d]:\n", i); 466 dev_dbg(dev, "\t.out_buf_id = %llu\n", 467 buf->output_pins[i].out_buf_id); 468 dev_dbg(dev, "\t.addr = 0x%x\n", buf->output_pins[i].addr); 469 dev_dbg(dev, "\t.compress = %d\n", 470 buf->output_pins[i].compress); 471 } 472 473 dev_dbg(dev, "send_irq_sof = 0x%x\n", buf->send_irq_sof); 474 dev_dbg(dev, "send_irq_eof = 0x%x\n", buf->send_irq_eof); 475 dev_dbg(dev, "send_resp_sof = 0x%x\n", buf->send_resp_sof); 476 dev_dbg(dev, "send_resp_eof = 0x%x\n", buf->send_resp_eof); 477 dev_dbg(dev, "send_irq_capture_ack = 0x%x\n", 478 buf->send_irq_capture_ack); 479 dev_dbg(dev, "send_irq_capture_done = 0x%x\n", 480 buf->send_irq_capture_done); 481 dev_dbg(dev, "send_resp_capture_ack = 0x%x\n", 482 buf->send_resp_capture_ack); 483 dev_dbg(dev, "send_resp_capture_done = 0x%x\n", 484 buf->send_resp_capture_done); 485 486 dev_dbg(dev, "-----------------------------------------------------\n"); 487 } 488