static int load_copro_firmware()

in fsi-master-ast-cf.c [829:878]


static int load_copro_firmware(struct fsi_master_acf *master)
{
	const struct firmware *fw;
	uint16_t sig = 0, wanted_sig;
	const u8 *data;
	size_t size = 0;
	int rc;

	/* Get the binary */
	rc = request_firmware(&fw, FW_FILE_NAME, master->dev);
	if (rc) {
		dev_err(
			master->dev, "Error %d to load firmware '%s' !\n",
			rc, FW_FILE_NAME);
		return rc;
	}

	/* Which image do we want ? (shared vs. split clock/data GPIOs) */
	if (master->gpio_clk_vreg == master->gpio_dat_vreg)
		wanted_sig = SYS_SIG_SHARED;
	else
		wanted_sig = SYS_SIG_SPLIT;
	dev_dbg(master->dev, "Looking for image sig %04x\n", wanted_sig);

	/* Try to find it */
	for (data = fw->data; data < (fw->data + fw->size);) {
		sig = be16_to_cpup((__be16 *)(data + HDR_OFFSET + HDR_SYS_SIG));
		size = be32_to_cpup((__be32 *)(data + HDR_OFFSET + HDR_FW_SIZE));
		if (sig == wanted_sig)
			break;
		data += size;
	}
	if (sig != wanted_sig) {
		dev_err(master->dev, "Failed to locate image sig %04x in FW blob\n",
			wanted_sig);
		rc = -ENODEV;
		goto release_fw;
	}
	if (size > master->cf_mem_size) {
		dev_err(master->dev, "FW size (%zd) bigger than memory reserve (%zd)\n",
			fw->size, master->cf_mem_size);
		rc = -ENOMEM;
	} else {
		memcpy_toio(master->cf_mem, data, size);
	}

release_fw:
	release_firmware(fw);
	return rc;
}