Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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 <linux/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 */
 60enum {
 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 */
 71enum {
 72	VSC_TOKEN_BOOTLOADER_REQ = 1,
 73	VSC_TOKEN_DUMP_RESP = 4,
 74	VSC_TOKEN_ERROR = 7,
 75};
 76
 77/* image type */
 78enum {
 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 */
 89enum {
 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
100struct 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
138struct vsc_rom_cmd_ack {
139	__le32 magic;
140	__u8 token;
141	__u8 type;
142	__u8 res[2];
143	__u8 payload[];
144};
145
146struct 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
178struct vsc_img {
179	__le32 magic;
180	__le32 option;
181	__le32 image_count;
182	__le32 image_location[VSC_IMG_CNT_MAX];
183};
184
185struct vsc_fw_sign {
186	__le32 magic;
187	__le32 image_size;
188	__u8 image[];
189};
190
191struct vsc_image_code_data {
192	/* fragment index */
193	u8 frag_index;
194	/* image type */
195	u8 image_type;
196};
197
198struct 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 */
219struct 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
238static 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 */
250static 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
301out_free_buff:
302	ACPI_FREE(buffer.pointer);
303
304	return ret;
305}
306
307static 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 || ack->token == VSC_TOKEN_ERROR) {
321		dev_err(fw_loader->dev, "CMD_DUMP_MEM error %d token %d\n", ret, ack->token);
322		return ret ?: -EINVAL;
323	}
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 || ack->token != VSC_TOKEN_DUMP_RESP) {
329		dev_err(fw_loader->dev, "CMD_GETCONT error %d token %d\n", ret, ack->token);
330		return ret ?: -EINVAL;
331	}
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		dev_err(fw_loader->dev, "mainstepping mismatch expected %d got %d\n",
338			VSC_MAINSTEPPING_VERSION_A, version);
339		return -EINVAL;
340	}
341
342	if (sub_version != VSC_SUBSTEPPING_VERSION_0 &&
343	    sub_version != VSC_SUBSTEPPING_VERSION_1) {
344		dev_err(fw_loader->dev, "substepping %d is out of supported range %d - %d\n",
345			sub_version, VSC_SUBSTEPPING_VERSION_0, VSC_SUBSTEPPING_VERSION_1);
346		return -EINVAL;
347	}
348
349	dev_info(fw_loader->dev, "silicon stepping version is %u:%u\n",
350		 version, sub_version);
351
352	/* identify strap information */
353	cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
354	cmd->cmd_id = VSC_CMD_DUMP_MEM;
355	cmd->data.dump_mem.addr = cpu_to_le32(VSC_STRAP_ADDR);
356	cmd->data.dump_mem.len = cpu_to_le16(sizeof(__le32));
357	ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE);
358	if (ret)
359		return ret;
360	if (ack->token == VSC_TOKEN_ERROR)
361		return -EINVAL;
362
363	cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
364	cmd->cmd_id = VSC_CMD_GET_CONT;
365	ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE);
366	if (ret)
367		return ret;
368	if (ack->token != VSC_TOKEN_DUMP_RESP)
369		return -EINVAL;
370
371	return 0;
372}
373
374static int vsc_identify_csi_image(struct vsc_fw_loader *fw_loader)
375{
376	const struct firmware *image;
377	struct vsc_fw_sign *sign;
378	struct vsc_img *img;
379	unsigned int i;
380	int ret;
381
382	ret = request_firmware(&image, VSC_CSI_IMAGE_NAME, fw_loader->dev);
383	if (ret)
384		return ret;
385
386	img = (struct vsc_img *)image->data;
387	if (!img) {
388		ret = -ENOENT;
389		goto err_release_image;
390	}
391
392	if (le32_to_cpu(img->magic) != VSC_MAGIC_FILE) {
393		ret = -EINVAL;
394		goto err_release_image;
395	}
396
397	if (le32_to_cpu(img->image_count) != VSC_CSI_IMG_CNT) {
398		ret = -EINVAL;
399		goto err_release_image;
400	}
401	fw_loader->count += le32_to_cpu(img->image_count) - 1;
402
403	fw_loader->option =
404		FIELD_GET(VSC_BOOT_IMG_OPTION_MASK, le32_to_cpu(img->option));
405
406	sign = (struct vsc_fw_sign *)
407		(img->image_location + le32_to_cpu(img->image_count));
408
409	for (i = 0; i < VSC_CSI_IMG_CNT; i++) {
410		/* mapping from CSI image index to image code data */
411		static const struct vsc_image_code_data csi_image_map[] = {
412			{ VSC_IMG_BOOTLOADER_FRAG, VSC_IMG_BOOTLOADER_TYPE },
413			{ VSC_IMG_CSI_SEM_FRAG, VSC_IMG_CSI_SEM_TYPE },
414			{ VSC_IMG_CSI_RUNTIME_FRAG, VSC_IMG_CSI_RUNTIME_TYPE },
415			{ VSC_IMG_CSI_EM7D_FRAG, VSC_IMG_CSI_EM7D_TYPE },
416		};
417		struct vsc_img_frag *frag;
418
419		if ((u8 *)sign + sizeof(*sign) > image->data + image->size) {
420			ret = -EINVAL;
421			goto err_release_image;
422		}
423
424		if (le32_to_cpu(sign->magic) != VSC_MAGIC_FW) {
425			ret = -EINVAL;
426			goto err_release_image;
427		}
428
429		if (!le32_to_cpu(img->image_location[i])) {
430			ret = -EINVAL;
431			goto err_release_image;
432		}
433
434		frag = &fw_loader->frags[csi_image_map[i].frag_index];
435
436		frag->data = sign->image;
437		frag->size = le32_to_cpu(sign->image_size);
438		frag->location = le32_to_cpu(img->image_location[i]);
439		frag->type = csi_image_map[i].image_type;
440
441		sign = (struct vsc_fw_sign *)
442			(sign->image + le32_to_cpu(sign->image_size));
443	}
444
445	fw_loader->csi = image;
446
447	return 0;
448
449err_release_image:
450	release_firmware(image);
451
452	return ret;
453}
454
455static int vsc_identify_ace_image(struct vsc_fw_loader *fw_loader)
456{
457	char path[VSC_IMAGE_PATH_MAX_LEN];
458	const struct firmware *image;
459	struct vsc_fw_sign *sign;
460	struct vsc_img *img;
461	unsigned int i;
462	int ret;
463
464	snprintf(path, sizeof(path), VSC_ACE_IMAGE_NAME_FMT,
465		 fw_loader->sensor_name);
466
467	ret = request_firmware(&image, path, fw_loader->dev);
468	if (ret)
469		return ret;
470
471	img = (struct vsc_img *)image->data;
472	if (!img) {
473		ret = -ENOENT;
474		goto err_release_image;
475	}
476
477	if (le32_to_cpu(img->magic) != VSC_MAGIC_FILE) {
478		ret = -EINVAL;
479		goto err_release_image;
480	}
481
482	if (le32_to_cpu(img->image_count) != VSC_ACE_IMG_CNT) {
483		ret = -EINVAL;
484		goto err_release_image;
485	}
486	fw_loader->count += le32_to_cpu(img->image_count);
487
488	sign = (struct vsc_fw_sign *)
489		(img->image_location + le32_to_cpu(img->image_count));
490
491	for (i = 0; i < VSC_ACE_IMG_CNT; i++) {
492		/* mapping from ACE image index to image code data */
493		static const struct vsc_image_code_data ace_image_map[] = {
494			{ VSC_IMG_ACE_VISION_FRAG, VSC_IMG_ACE_VISION_TYPE },
495			{ VSC_IMG_ACE_CFG_FRAG, VSC_IMG_ACE_CFG_TYPE },
496		};
497		struct vsc_img_frag *frag, *last_frag;
498		u8 frag_index;
499
500		if ((u8 *)sign + sizeof(*sign) > image->data + image->size) {
501			ret = -EINVAL;
502			goto err_release_image;
503		}
504
505		if (le32_to_cpu(sign->magic) != VSC_MAGIC_FW) {
506			ret = -EINVAL;
507			goto err_release_image;
508		}
509
510		frag_index = ace_image_map[i].frag_index;
511		frag = &fw_loader->frags[frag_index];
512
513		frag->data = sign->image;
514		frag->size = le32_to_cpu(sign->image_size);
515		frag->location = le32_to_cpu(img->image_location[i]);
516		frag->type = ace_image_map[i].image_type;
517
518		if (!frag->location) {
519			last_frag = &fw_loader->frags[frag_index - 1];
520			frag->location =
521				ALIGN(last_frag->location + last_frag->size, SZ_4K);
522		}
523
524		sign = (struct vsc_fw_sign *)
525			(sign->image + le32_to_cpu(sign->image_size));
526	}
527
528	fw_loader->ace = image;
529
530	return 0;
531
532err_release_image:
533	release_firmware(image);
534
535	return ret;
536}
537
538static int vsc_identify_cfg_image(struct vsc_fw_loader *fw_loader)
539{
540	struct vsc_img_frag *frag = &fw_loader->frags[VSC_IMG_SKU_CFG_FRAG];
541	char path[VSC_IMAGE_PATH_MAX_LEN];
542	const struct firmware *image;
543	u32 size;
544	int ret;
545
546	snprintf(path, sizeof(path), VSC_CFG_IMAGE_NAME_FMT,
547		 fw_loader->sensor_name);
548
549	ret = request_firmware(&image, path, fw_loader->dev);
550	if (ret)
551		return ret;
552
553	/* identify image size */
554	if (image->size <= sizeof(u32) || image->size > VSC_SKU_MAX_SIZE) {
555		ret = -EINVAL;
556		goto err_release_image;
557	}
558
559	size = le32_to_cpu(*((__le32 *)image->data)) + sizeof(u32);
560	if (image->size != size) {
561		ret = -EINVAL;
562		goto err_release_image;
563	}
564
565	frag->data = image->data;
566	frag->size = image->size;
567	frag->type = VSC_IMG_SKU_CFG_TYPE;
568	frag->location = VSC_SKU_CFG_LOCATION;
569
570	fw_loader->cfg = image;
571
572	return 0;
573
574err_release_image:
575	release_firmware(image);
576
577	return ret;
578}
579
580static int vsc_download_bootloader(struct vsc_fw_loader *fw_loader)
581{
582	struct vsc_img_frag *frag = &fw_loader->frags[VSC_IMG_BOOTLOADER_FRAG];
583	struct vsc_rom_cmd_ack *ack = fw_loader->rx_buf;
584	struct vsc_rom_cmd *cmd = fw_loader->tx_buf;
585	u32 len, c_len;
586	size_t remain;
587	const u8 *p;
588	int ret;
589
590	cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
591	cmd->cmd_id = VSC_CMD_QUERY;
592	ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE);
593	if (ret)
594		return ret;
595	if (ack->token != VSC_TOKEN_DUMP_RESP &&
596	    ack->token != VSC_TOKEN_BOOTLOADER_REQ)
597		return -EINVAL;
598
599	cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
600	cmd->cmd_id = VSC_CMD_DL_START;
601	cmd->data.dl_start.option = cpu_to_le16(fw_loader->option);
602	cmd->data.dl_start.img_type = frag->type;
603	cmd->data.dl_start.img_len = cpu_to_le32(frag->size);
604	cmd->data.dl_start.img_loc = cpu_to_le32(frag->location);
605
606	c_len = offsetof(struct vsc_rom_cmd, data.dl_start.crc);
607	cmd->data.dl_start.crc = cpu_to_le32(vsc_sum_crc(cmd, c_len));
608
609	ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_ROM_PKG_SIZE);
610	if (ret)
611		return ret;
612
613	p = frag->data;
614	remain = frag->size;
615
616	/* download image data */
617	while (remain > 0) {
618		len = min(remain, sizeof(cmd->data.dl_cont.payload));
619
620		cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
621		cmd->cmd_id = VSC_CMD_DL_CONT;
622		cmd->data.dl_cont.len = cpu_to_le16(len);
623		cmd->data.dl_cont.end_flag = remain == len;
624		memcpy(cmd->data.dl_cont.payload, p, len);
625
626		ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_ROM_PKG_SIZE);
627		if (ret)
628			return ret;
629
630		p += len;
631		remain -= len;
632	}
633
634	return 0;
635}
636
637static int vsc_download_firmware(struct vsc_fw_loader *fw_loader)
638{
639	struct vsc_fw_cmd *cmd = fw_loader->tx_buf;
640	unsigned int i, index = 0;
641	u32 c_len;
642	int ret;
643
644	cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
645	cmd->cmd_id = VSC_CMD_DL_SET;
646	cmd->data.dl_set.img_cnt = cpu_to_le16(fw_loader->count);
647	put_unaligned_le16(fw_loader->option, &cmd->data.dl_set.option);
648
649	for (i = VSC_IMG_CSI_SEM_FRAG; i <= VSC_IMG_CSI_EM7D_FRAG; i++) {
650		struct vsc_img_frag *frag = &fw_loader->frags[i];
651
652		cmd->data.dl_set.payload[index++] = cpu_to_le32(frag->location);
653		cmd->data.dl_set.payload[index++] = cpu_to_le32(frag->size);
654	}
655
656	c_len = offsetof(struct vsc_fw_cmd, data.dl_set.payload[index]);
657	cmd->data.dl_set.payload[index] = cpu_to_le32(vsc_sum_crc(cmd, c_len));
658
659	ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_FW_PKG_SIZE);
660	if (ret)
661		return ret;
662
663	for (i = VSC_IMG_CSI_SEM_FRAG; i < VSC_IMG_FRAG_MAX; i++) {
664		struct vsc_img_frag *frag = &fw_loader->frags[i];
665		const u8 *p;
666		u32 remain;
667
668		cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
669		cmd->cmd_id = VSC_CMD_DL_START;
670		cmd->data.dl_start.img_type = frag->type;
671		cmd->data.dl_start.img_len = cpu_to_le32(frag->size);
672		cmd->data.dl_start.img_loc = cpu_to_le32(frag->location);
673		put_unaligned_le16(fw_loader->option, &cmd->data.dl_start.option);
674
675		c_len = offsetof(struct vsc_fw_cmd, data.dl_start.crc);
676		cmd->data.dl_start.crc = cpu_to_le32(vsc_sum_crc(cmd, c_len));
677
678		ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_FW_PKG_SIZE);
679		if (ret)
680			return ret;
681
682		p = frag->data;
683		remain = frag->size;
684
685		/* download image data */
686		while (remain > 0) {
687			u32 len = min(remain, VSC_FW_PKG_SIZE);
688
689			memcpy(fw_loader->tx_buf, p, len);
690			memset(fw_loader->tx_buf + len, 0, VSC_FW_PKG_SIZE - len);
691
692			ret = vsc_tp_rom_xfer(fw_loader->tp, fw_loader->tx_buf,
693					      NULL, VSC_FW_PKG_SIZE);
694			if (ret)
695				break;
696
697			p += len;
698			remain -= len;
699		}
700	}
701
702	cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
703	cmd->cmd_id = VSC_CMD_CAM_BOOT;
704
705	c_len = offsetof(struct vsc_fw_cmd, data.dl_start.crc);
706	cmd->data.boot.crc = cpu_to_le32(vsc_sum_crc(cmd, c_len));
707
708	return vsc_tp_rom_xfer(fw_loader->tp, cmd, NULL, VSC_FW_PKG_SIZE);
709}
710
711/**
712 * vsc_tp_init - init vsc_tp
713 * @tp: vsc_tp device handle
714 * @dev: device node for mei vsc device
715 * Return: 0 in case of success, negative value in case of error
716 */
717int vsc_tp_init(struct vsc_tp *tp, struct device *dev)
718{
719	struct vsc_fw_loader *fw_loader __free(kfree) = NULL;
720	void *tx_buf __free(kfree) = NULL;
721	void *rx_buf __free(kfree) = NULL;
722	int ret;
723
724	fw_loader = kzalloc(sizeof(*fw_loader), GFP_KERNEL);
725	if (!fw_loader)
726		return -ENOMEM;
727
728	tx_buf = kzalloc(VSC_FW_PKG_SIZE, GFP_KERNEL);
729	if (!tx_buf)
730		return -ENOMEM;
731
732	rx_buf = kzalloc(VSC_FW_PKG_SIZE, GFP_KERNEL);
733	if (!rx_buf)
734		return -ENOMEM;
735
736	fw_loader->tx_buf = tx_buf;
737	fw_loader->rx_buf = rx_buf;
738
739	fw_loader->tp = tp;
740	fw_loader->dev = dev;
741
742	ret = vsc_get_sensor_name(fw_loader, dev);
743	if (ret)
744		return ret;
745
746	ret = vsc_identify_silicon(fw_loader);
747	if (ret)
748		return ret;
749
750	ret = vsc_identify_csi_image(fw_loader);
751	if (ret)
752		return ret;
753
754	ret = vsc_identify_ace_image(fw_loader);
755	if (ret)
756		goto err_release_csi;
757
758	ret = vsc_identify_cfg_image(fw_loader);
759	if (ret)
760		goto err_release_ace;
761
762	ret = vsc_download_bootloader(fw_loader);
763	if (!ret)
764		ret = vsc_download_firmware(fw_loader);
765
766	release_firmware(fw_loader->cfg);
767
768err_release_ace:
769	release_firmware(fw_loader->ace);
770
771err_release_csi:
772	release_firmware(fw_loader->csi);
773
774	return ret;
775}
776EXPORT_SYMBOL_NS_GPL(vsc_tp_init, "VSC_TP");