1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2023, Intel Corporation. 4 * Intel Visual Sensing Controller Transport Layer Linux driver 5 */ 6 7 #include <linux/acpi.h> 8 #include <linux/align.h> 9 #include <linux/bitfield.h> 10 #include <linux/bits.h> 11 #include <linux/cleanup.h> 12 #include <linux/firmware.h> 13 #include <linux/sizes.h> 14 #include <linux/slab.h> 15 #include <linux/string_helpers.h> 16 #include <linux/types.h> 17 18 #include <asm-generic/unaligned.h> 19 20 #include "vsc-tp.h" 21 22 #define VSC_MAGIC_NUM 0x49505343 /* IPSC */ 23 #define VSC_MAGIC_FW 0x49574653 /* IWFS */ 24 #define VSC_MAGIC_FILE 0x46564353 /* FVCS */ 25 26 #define VSC_ADDR_BASE 0xE0030000 27 #define VSC_EFUSE_ADDR (VSC_ADDR_BASE + 0x038) 28 #define VSC_STRAP_ADDR (VSC_ADDR_BASE + 0x100) 29 30 #define VSC_MAINSTEPPING_VERSION_MASK GENMASK(7, 4) 31 #define VSC_MAINSTEPPING_VERSION_A 0 32 33 #define VSC_SUBSTEPPING_VERSION_MASK GENMASK(3, 0) 34 #define VSC_SUBSTEPPING_VERSION_0 0 35 #define VSC_SUBSTEPPING_VERSION_1 2 36 37 #define VSC_BOOT_IMG_OPTION_MASK GENMASK(15, 0) 38 39 #define VSC_SKU_CFG_LOCATION 0x5001A000 40 #define VSC_SKU_MAX_SIZE 4100u 41 42 #define VSC_ACE_IMG_CNT 2 43 #define VSC_CSI_IMG_CNT 4 44 #define VSC_IMG_CNT_MAX 6 45 46 #define VSC_ROM_PKG_SIZE 256u 47 #define VSC_FW_PKG_SIZE 512u 48 49 #define VSC_IMAGE_DIR "intel/vsc/" 50 51 #define VSC_CSI_IMAGE_NAME VSC_IMAGE_DIR "ivsc_fw.bin" 52 #define VSC_ACE_IMAGE_NAME_FMT VSC_IMAGE_DIR "ivsc_pkg_%s_0.bin" 53 #define VSC_CFG_IMAGE_NAME_FMT VSC_IMAGE_DIR "ivsc_skucfg_%s_0_1.bin" 54 55 #define VSC_IMAGE_PATH_MAX_LEN 64 56 57 #define VSC_SENSOR_NAME_MAX_LEN 16 58 59 /* command id */ 60 enum { 61 VSC_CMD_QUERY = 0, 62 VSC_CMD_DL_SET = 1, 63 VSC_CMD_DL_START = 2, 64 VSC_CMD_DL_CONT = 3, 65 VSC_CMD_DUMP_MEM = 4, 66 VSC_CMD_GET_CONT = 8, 67 VSC_CMD_CAM_BOOT = 10, 68 }; 69 70 /* command ack token */ 71 enum { 72 VSC_TOKEN_BOOTLOADER_REQ = 1, 73 VSC_TOKEN_DUMP_RESP = 4, 74 VSC_TOKEN_ERROR = 7, 75 }; 76 77 /* image type */ 78 enum { 79 VSC_IMG_BOOTLOADER_TYPE = 1, 80 VSC_IMG_CSI_EM7D_TYPE, 81 VSC_IMG_CSI_SEM_TYPE, 82 VSC_IMG_CSI_RUNTIME_TYPE, 83 VSC_IMG_ACE_VISION_TYPE, 84 VSC_IMG_ACE_CFG_TYPE, 85 VSC_IMG_SKU_CFG_TYPE, 86 }; 87 88 /* image fragments */ 89 enum { 90 VSC_IMG_BOOTLOADER_FRAG, 91 VSC_IMG_CSI_SEM_FRAG, 92 VSC_IMG_CSI_RUNTIME_FRAG, 93 VSC_IMG_ACE_VISION_FRAG, 94 VSC_IMG_ACE_CFG_FRAG, 95 VSC_IMG_CSI_EM7D_FRAG, 96 VSC_IMG_SKU_CFG_FRAG, 97 VSC_IMG_FRAG_MAX 98 }; 99 100 struct vsc_rom_cmd { 101 __le32 magic; 102 __u8 cmd_id; 103 union { 104 /* download start */ 105 struct { 106 __u8 img_type; 107 __le16 option; 108 __le32 img_len; 109 __le32 img_loc; 110 __le32 crc; 111 DECLARE_FLEX_ARRAY(__u8, res); 112 } __packed dl_start; 113 /* download set */ 114 struct { 115 __u8 option; 116 __le16 img_cnt; 117 DECLARE_FLEX_ARRAY(__le32, payload); 118 } __packed dl_set; 119 /* download continue */ 120 struct { 121 __u8 end_flag; 122 __le16 len; 123 /* 8 is the offset of payload */ 124 __u8 payload[VSC_ROM_PKG_SIZE - 8]; 125 } __packed dl_cont; 126 /* dump memory */ 127 struct { 128 __u8 res; 129 __le16 len; 130 __le32 addr; 131 DECLARE_FLEX_ARRAY(__u8, payload); 132 } __packed dump_mem; 133 /* 5 is the offset of padding */ 134 __u8 padding[VSC_ROM_PKG_SIZE - 5]; 135 } data; 136 }; 137 138 struct vsc_rom_cmd_ack { 139 __le32 magic; 140 __u8 token; 141 __u8 type; 142 __u8 res[2]; 143 __u8 payload[]; 144 }; 145 146 struct vsc_fw_cmd { 147 __le32 magic; 148 __u8 cmd_id; 149 union { 150 struct { 151 __le16 option; 152 __u8 img_type; 153 __le32 img_len; 154 __le32 img_loc; 155 __le32 crc; 156 DECLARE_FLEX_ARRAY(__u8, res); 157 } __packed dl_start; 158 struct { 159 __le16 option; 160 __u8 img_cnt; 161 DECLARE_FLEX_ARRAY(__le32, payload); 162 } __packed dl_set; 163 struct { 164 __le32 addr; 165 __u8 len; 166 DECLARE_FLEX_ARRAY(__u8, payload); 167 } __packed dump_mem; 168 struct { 169 __u8 resv[3]; 170 __le32 crc; 171 DECLARE_FLEX_ARRAY(__u8, payload); 172 } __packed boot; 173 /* 5 is the offset of padding */ 174 __u8 padding[VSC_FW_PKG_SIZE - 5]; 175 } data; 176 }; 177 178 struct vsc_img { 179 __le32 magic; 180 __le32 option; 181 __le32 image_count; 182 __le32 image_location[VSC_IMG_CNT_MAX]; 183 }; 184 185 struct vsc_fw_sign { 186 __le32 magic; 187 __le32 image_size; 188 __u8 image[]; 189 }; 190 191 struct vsc_image_code_data { 192 /* fragment index */ 193 u8 frag_index; 194 /* image type */ 195 u8 image_type; 196 }; 197 198 struct vsc_img_frag { 199 u8 type; 200 u32 location; 201 const u8 *data; 202 u32 size; 203 }; 204 205 /** 206 * struct vsc_fw_loader - represent vsc firmware loader 207 * @dev: device used to request firmware 208 * @tp: transport layer used with the firmware loader 209 * @csi: CSI image 210 * @ace: ACE image 211 * @cfg: config image 212 * @tx_buf: tx buffer 213 * @rx_buf: rx buffer 214 * @option: command option 215 * @count: total image count 216 * @sensor_name: camera sensor name 217 * @frags: image fragments 218 */ 219 struct vsc_fw_loader { 220 struct device *dev; 221 struct vsc_tp *tp; 222 223 const struct firmware *csi; 224 const struct firmware *ace; 225 const struct firmware *cfg; 226 227 void *tx_buf; 228 void *rx_buf; 229 230 u16 option; 231 u16 count; 232 233 char sensor_name[VSC_SENSOR_NAME_MAX_LEN]; 234 235 struct vsc_img_frag frags[VSC_IMG_FRAG_MAX]; 236 }; 237 238 static inline u32 vsc_sum_crc(void *data, size_t size) 239 { 240 u32 crc = 0; 241 size_t i; 242 243 for (i = 0; i < size; i++) 244 crc += *((u8 *)data + i); 245 246 return crc; 247 } 248 249 /* get sensor name to construct image name */ 250 static int vsc_get_sensor_name(struct vsc_fw_loader *fw_loader, 251 struct device *dev) 252 { 253 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER }; 254 union acpi_object obj = { 255 .integer.type = ACPI_TYPE_INTEGER, 256 .integer.value = 1, 257 }; 258 struct acpi_object_list arg_list = { 259 .count = 1, 260 .pointer = &obj, 261 }; 262 union acpi_object *ret_obj; 263 acpi_handle handle; 264 acpi_status status; 265 int ret = 0; 266 267 handle = ACPI_HANDLE(dev); 268 if (!handle) 269 return -EINVAL; 270 271 status = acpi_evaluate_object(handle, "SID", &arg_list, &buffer); 272 if (ACPI_FAILURE(status)) { 273 dev_err(dev, "can't evaluate SID method: %d\n", status); 274 return -ENODEV; 275 } 276 277 ret_obj = buffer.pointer; 278 if (!ret_obj) { 279 dev_err(dev, "can't locate ACPI buffer\n"); 280 return -ENODEV; 281 } 282 283 if (ret_obj->type != ACPI_TYPE_STRING) { 284 dev_err(dev, "found non-string entry\n"); 285 ret = -ENODEV; 286 goto out_free_buff; 287 } 288 289 /* string length excludes trailing NUL */ 290 if (ret_obj->string.length >= sizeof(fw_loader->sensor_name)) { 291 dev_err(dev, "sensor name buffer too small\n"); 292 ret = -EINVAL; 293 goto out_free_buff; 294 } 295 296 memcpy(fw_loader->sensor_name, ret_obj->string.pointer, 297 ret_obj->string.length); 298 299 string_lower(fw_loader->sensor_name, fw_loader->sensor_name); 300 301 out_free_buff: 302 ACPI_FREE(buffer.pointer); 303 304 return ret; 305 } 306 307 static int vsc_identify_silicon(struct vsc_fw_loader *fw_loader) 308 { 309 struct vsc_rom_cmd_ack *ack = fw_loader->rx_buf; 310 struct vsc_rom_cmd *cmd = fw_loader->tx_buf; 311 u8 version, sub_version; 312 int ret; 313 314 /* identify stepping information */ 315 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 316 cmd->cmd_id = VSC_CMD_DUMP_MEM; 317 cmd->data.dump_mem.addr = cpu_to_le32(VSC_EFUSE_ADDR); 318 cmd->data.dump_mem.len = cpu_to_le16(sizeof(__le32)); 319 ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE); 320 if (ret) 321 return ret; 322 if (ack->token == VSC_TOKEN_ERROR) 323 return -EINVAL; 324 325 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 326 cmd->cmd_id = VSC_CMD_GET_CONT; 327 ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE); 328 if (ret) 329 return ret; 330 if (ack->token != VSC_TOKEN_DUMP_RESP) 331 return -EINVAL; 332 333 version = FIELD_GET(VSC_MAINSTEPPING_VERSION_MASK, ack->payload[0]); 334 sub_version = FIELD_GET(VSC_SUBSTEPPING_VERSION_MASK, ack->payload[0]); 335 336 if (version != VSC_MAINSTEPPING_VERSION_A) 337 return -EINVAL; 338 339 if (sub_version != VSC_SUBSTEPPING_VERSION_0 && 340 sub_version != VSC_SUBSTEPPING_VERSION_1) 341 return -EINVAL; 342 343 dev_info(fw_loader->dev, "silicon stepping version is %u:%u\n", 344 version, sub_version); 345 346 /* identify strap information */ 347 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 348 cmd->cmd_id = VSC_CMD_DUMP_MEM; 349 cmd->data.dump_mem.addr = cpu_to_le32(VSC_STRAP_ADDR); 350 cmd->data.dump_mem.len = cpu_to_le16(sizeof(__le32)); 351 ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE); 352 if (ret) 353 return ret; 354 if (ack->token == VSC_TOKEN_ERROR) 355 return -EINVAL; 356 357 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 358 cmd->cmd_id = VSC_CMD_GET_CONT; 359 ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE); 360 if (ret) 361 return ret; 362 if (ack->token != VSC_TOKEN_DUMP_RESP) 363 return -EINVAL; 364 365 return 0; 366 } 367 368 static int vsc_identify_csi_image(struct vsc_fw_loader *fw_loader) 369 { 370 const struct firmware *image; 371 struct vsc_fw_sign *sign; 372 struct vsc_img *img; 373 unsigned int i; 374 int ret; 375 376 ret = request_firmware(&image, VSC_CSI_IMAGE_NAME, fw_loader->dev); 377 if (ret) 378 return ret; 379 380 img = (struct vsc_img *)image->data; 381 if (!img) { 382 ret = -ENOENT; 383 goto err_release_image; 384 } 385 386 if (le32_to_cpu(img->magic) != VSC_MAGIC_FILE) { 387 ret = -EINVAL; 388 goto err_release_image; 389 } 390 391 if (le32_to_cpu(img->image_count) != VSC_CSI_IMG_CNT) { 392 ret = -EINVAL; 393 goto err_release_image; 394 } 395 fw_loader->count += le32_to_cpu(img->image_count) - 1; 396 397 fw_loader->option = 398 FIELD_GET(VSC_BOOT_IMG_OPTION_MASK, le32_to_cpu(img->option)); 399 400 sign = (struct vsc_fw_sign *) 401 (img->image_location + le32_to_cpu(img->image_count)); 402 403 for (i = 0; i < VSC_CSI_IMG_CNT; i++) { 404 /* mapping from CSI image index to image code data */ 405 static const struct vsc_image_code_data csi_image_map[] = { 406 { VSC_IMG_BOOTLOADER_FRAG, VSC_IMG_BOOTLOADER_TYPE }, 407 { VSC_IMG_CSI_SEM_FRAG, VSC_IMG_CSI_SEM_TYPE }, 408 { VSC_IMG_CSI_RUNTIME_FRAG, VSC_IMG_CSI_RUNTIME_TYPE }, 409 { VSC_IMG_CSI_EM7D_FRAG, VSC_IMG_CSI_EM7D_TYPE }, 410 }; 411 struct vsc_img_frag *frag; 412 413 if ((u8 *)sign + sizeof(*sign) > image->data + image->size) { 414 ret = -EINVAL; 415 goto err_release_image; 416 } 417 418 if (le32_to_cpu(sign->magic) != VSC_MAGIC_FW) { 419 ret = -EINVAL; 420 goto err_release_image; 421 } 422 423 if (!le32_to_cpu(img->image_location[i])) { 424 ret = -EINVAL; 425 goto err_release_image; 426 } 427 428 frag = &fw_loader->frags[csi_image_map[i].frag_index]; 429 430 frag->data = sign->image; 431 frag->size = le32_to_cpu(sign->image_size); 432 frag->location = le32_to_cpu(img->image_location[i]); 433 frag->type = csi_image_map[i].image_type; 434 435 sign = (struct vsc_fw_sign *) 436 (sign->image + le32_to_cpu(sign->image_size)); 437 } 438 439 fw_loader->csi = image; 440 441 return 0; 442 443 err_release_image: 444 release_firmware(image); 445 446 return ret; 447 } 448 449 static int vsc_identify_ace_image(struct vsc_fw_loader *fw_loader) 450 { 451 char path[VSC_IMAGE_PATH_MAX_LEN]; 452 const struct firmware *image; 453 struct vsc_fw_sign *sign; 454 struct vsc_img *img; 455 unsigned int i; 456 int ret; 457 458 snprintf(path, sizeof(path), VSC_ACE_IMAGE_NAME_FMT, 459 fw_loader->sensor_name); 460 461 ret = request_firmware(&image, path, fw_loader->dev); 462 if (ret) 463 return ret; 464 465 img = (struct vsc_img *)image->data; 466 if (!img) { 467 ret = -ENOENT; 468 goto err_release_image; 469 } 470 471 if (le32_to_cpu(img->magic) != VSC_MAGIC_FILE) { 472 ret = -EINVAL; 473 goto err_release_image; 474 } 475 476 if (le32_to_cpu(img->image_count) != VSC_ACE_IMG_CNT) { 477 ret = -EINVAL; 478 goto err_release_image; 479 } 480 fw_loader->count += le32_to_cpu(img->image_count); 481 482 sign = (struct vsc_fw_sign *) 483 (img->image_location + le32_to_cpu(img->image_count)); 484 485 for (i = 0; i < VSC_ACE_IMG_CNT; i++) { 486 /* mapping from ACE image index to image code data */ 487 static const struct vsc_image_code_data ace_image_map[] = { 488 { VSC_IMG_ACE_VISION_FRAG, VSC_IMG_ACE_VISION_TYPE }, 489 { VSC_IMG_ACE_CFG_FRAG, VSC_IMG_ACE_CFG_TYPE }, 490 }; 491 struct vsc_img_frag *frag, *last_frag; 492 u8 frag_index; 493 494 if ((u8 *)sign + sizeof(*sign) > image->data + image->size) { 495 ret = -EINVAL; 496 goto err_release_image; 497 } 498 499 if (le32_to_cpu(sign->magic) != VSC_MAGIC_FW) { 500 ret = -EINVAL; 501 goto err_release_image; 502 } 503 504 frag_index = ace_image_map[i].frag_index; 505 frag = &fw_loader->frags[frag_index]; 506 507 frag->data = sign->image; 508 frag->size = le32_to_cpu(sign->image_size); 509 frag->location = le32_to_cpu(img->image_location[i]); 510 frag->type = ace_image_map[i].image_type; 511 512 if (!frag->location) { 513 last_frag = &fw_loader->frags[frag_index - 1]; 514 frag->location = 515 ALIGN(last_frag->location + last_frag->size, SZ_4K); 516 } 517 518 sign = (struct vsc_fw_sign *) 519 (sign->image + le32_to_cpu(sign->image_size)); 520 } 521 522 fw_loader->ace = image; 523 524 return 0; 525 526 err_release_image: 527 release_firmware(image); 528 529 return ret; 530 } 531 532 static int vsc_identify_cfg_image(struct vsc_fw_loader *fw_loader) 533 { 534 struct vsc_img_frag *frag = &fw_loader->frags[VSC_IMG_SKU_CFG_FRAG]; 535 char path[VSC_IMAGE_PATH_MAX_LEN]; 536 const struct firmware *image; 537 u32 size; 538 int ret; 539 540 snprintf(path, sizeof(path), VSC_CFG_IMAGE_NAME_FMT, 541 fw_loader->sensor_name); 542 543 ret = request_firmware(&image, path, fw_loader->dev); 544 if (ret) 545 return ret; 546 547 /* identify image size */ 548 if (image->size <= sizeof(u32) || image->size > VSC_SKU_MAX_SIZE) { 549 ret = -EINVAL; 550 goto err_release_image; 551 } 552 553 size = le32_to_cpu(*((__le32 *)image->data)) + sizeof(u32); 554 if (image->size != size) { 555 ret = -EINVAL; 556 goto err_release_image; 557 } 558 559 frag->data = image->data; 560 frag->size = image->size; 561 frag->type = VSC_IMG_SKU_CFG_TYPE; 562 frag->location = VSC_SKU_CFG_LOCATION; 563 564 fw_loader->cfg = image; 565 566 return 0; 567 568 err_release_image: 569 release_firmware(image); 570 571 return ret; 572 } 573 574 static int vsc_download_bootloader(struct vsc_fw_loader *fw_loader) 575 { 576 struct vsc_img_frag *frag = &fw_loader->frags[VSC_IMG_BOOTLOADER_FRAG]; 577 struct vsc_rom_cmd_ack *ack = fw_loader->rx_buf; 578 struct vsc_rom_cmd *cmd = fw_loader->tx_buf; 579 u32 len, c_len; 580 size_t remain; 581 const u8 *p; 582 int ret; 583 584 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 585 cmd->cmd_id = VSC_CMD_QUERY; 586 ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE); 587 if (ret) 588 return ret; 589 if (ack->token != VSC_TOKEN_DUMP_RESP && 590 ack->token != VSC_TOKEN_BOOTLOADER_REQ) 591 return -EINVAL; 592 593 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 594 cmd->cmd_id = VSC_CMD_DL_START; 595 cmd->data.dl_start.option = cpu_to_le16(fw_loader->option); 596 cmd->data.dl_start.img_type = frag->type; 597 cmd->data.dl_start.img_len = cpu_to_le32(frag->size); 598 cmd->data.dl_start.img_loc = cpu_to_le32(frag->location); 599 600 c_len = offsetof(struct vsc_rom_cmd, data.dl_start.crc); 601 cmd->data.dl_start.crc = cpu_to_le32(vsc_sum_crc(cmd, c_len)); 602 603 ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_ROM_PKG_SIZE); 604 if (ret) 605 return ret; 606 607 p = frag->data; 608 remain = frag->size; 609 610 /* download image data */ 611 while (remain > 0) { 612 len = min(remain, sizeof(cmd->data.dl_cont.payload)); 613 614 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 615 cmd->cmd_id = VSC_CMD_DL_CONT; 616 cmd->data.dl_cont.len = cpu_to_le16(len); 617 cmd->data.dl_cont.end_flag = remain == len; 618 memcpy(cmd->data.dl_cont.payload, p, len); 619 620 ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_ROM_PKG_SIZE); 621 if (ret) 622 return ret; 623 624 p += len; 625 remain -= len; 626 } 627 628 return 0; 629 } 630 631 static int vsc_download_firmware(struct vsc_fw_loader *fw_loader) 632 { 633 struct vsc_fw_cmd *cmd = fw_loader->tx_buf; 634 unsigned int i, index = 0; 635 u32 c_len; 636 int ret; 637 638 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 639 cmd->cmd_id = VSC_CMD_DL_SET; 640 cmd->data.dl_set.img_cnt = cpu_to_le16(fw_loader->count); 641 put_unaligned_le16(fw_loader->option, &cmd->data.dl_set.option); 642 643 for (i = VSC_IMG_CSI_SEM_FRAG; i <= VSC_IMG_CSI_EM7D_FRAG; i++) { 644 struct vsc_img_frag *frag = &fw_loader->frags[i]; 645 646 cmd->data.dl_set.payload[index++] = cpu_to_le32(frag->location); 647 cmd->data.dl_set.payload[index++] = cpu_to_le32(frag->size); 648 } 649 650 c_len = offsetof(struct vsc_fw_cmd, data.dl_set.payload[index]); 651 cmd->data.dl_set.payload[index] = cpu_to_le32(vsc_sum_crc(cmd, c_len)); 652 653 ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_FW_PKG_SIZE); 654 if (ret) 655 return ret; 656 657 for (i = VSC_IMG_CSI_SEM_FRAG; i < VSC_IMG_FRAG_MAX; i++) { 658 struct vsc_img_frag *frag = &fw_loader->frags[i]; 659 const u8 *p; 660 u32 remain; 661 662 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 663 cmd->cmd_id = VSC_CMD_DL_START; 664 cmd->data.dl_start.img_type = frag->type; 665 cmd->data.dl_start.img_len = cpu_to_le32(frag->size); 666 cmd->data.dl_start.img_loc = cpu_to_le32(frag->location); 667 put_unaligned_le16(fw_loader->option, &cmd->data.dl_start.option); 668 669 c_len = offsetof(struct vsc_fw_cmd, data.dl_start.crc); 670 cmd->data.dl_start.crc = cpu_to_le32(vsc_sum_crc(cmd, c_len)); 671 672 ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_FW_PKG_SIZE); 673 if (ret) 674 return ret; 675 676 p = frag->data; 677 remain = frag->size; 678 679 /* download image data */ 680 while (remain > 0) { 681 u32 len = min(remain, VSC_FW_PKG_SIZE); 682 683 memcpy(fw_loader->tx_buf, p, len); 684 memset(fw_loader->tx_buf + len, 0, VSC_FW_PKG_SIZE - len); 685 686 ret = vsc_tp_rom_xfer(fw_loader->tp, fw_loader->tx_buf, 687 NULL, VSC_FW_PKG_SIZE); 688 if (ret) 689 break; 690 691 p += len; 692 remain -= len; 693 } 694 } 695 696 cmd->magic = cpu_to_le32(VSC_MAGIC_NUM); 697 cmd->cmd_id = VSC_CMD_CAM_BOOT; 698 699 c_len = offsetof(struct vsc_fw_cmd, data.dl_start.crc); 700 cmd->data.boot.crc = cpu_to_le32(vsc_sum_crc(cmd, c_len)); 701 702 return vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_FW_PKG_SIZE); 703 } 704 705 /** 706 * vsc_tp_init - init vsc_tp 707 * @tp: vsc_tp device handle 708 * @dev: device node for mei vsc device 709 * Return: 0 in case of success, negative value in case of error 710 */ 711 int vsc_tp_init(struct vsc_tp *tp, struct device *dev) 712 { 713 struct vsc_fw_loader *fw_loader __free(kfree) = NULL; 714 void *tx_buf __free(kfree) = NULL; 715 void *rx_buf __free(kfree) = NULL; 716 int ret; 717 718 fw_loader = kzalloc(sizeof(*fw_loader), GFP_KERNEL); 719 if (!fw_loader) 720 return -ENOMEM; 721 722 tx_buf = kzalloc(VSC_FW_PKG_SIZE, GFP_KERNEL); 723 if (!tx_buf) 724 return -ENOMEM; 725 726 rx_buf = kzalloc(VSC_FW_PKG_SIZE, GFP_KERNEL); 727 if (!rx_buf) 728 return -ENOMEM; 729 730 fw_loader->tx_buf = tx_buf; 731 fw_loader->rx_buf = rx_buf; 732 733 fw_loader->tp = tp; 734 fw_loader->dev = dev; 735 736 ret = vsc_get_sensor_name(fw_loader, dev); 737 if (ret) 738 return ret; 739 740 ret = vsc_identify_silicon(fw_loader); 741 if (ret) 742 return ret; 743 744 ret = vsc_identify_csi_image(fw_loader); 745 if (ret) 746 return ret; 747 748 ret = vsc_identify_ace_image(fw_loader); 749 if (ret) 750 goto err_release_csi; 751 752 ret = vsc_identify_cfg_image(fw_loader); 753 if (ret) 754 goto err_release_ace; 755 756 ret = vsc_download_bootloader(fw_loader); 757 if (!ret) 758 ret = vsc_download_firmware(fw_loader); 759 760 release_firmware(fw_loader->cfg); 761 762 err_release_ace: 763 release_firmware(fw_loader->ace); 764 765 err_release_csi: 766 release_firmware(fw_loader->csi); 767 768 return ret; 769 } 770 EXPORT_SYMBOL_NS_GPL(vsc_tp_init, VSC_TP); 771