Exemplo n.º 1
0
static int fdma_load_elf(const struct firmware *fw, struct fdma *fdma)
{
	struct ELF32_info *elfinfo = NULL;
	int i;
	int fw_major, fw_minor;
	int hw_major, hw_minor;
	int res;

	if (!fw) {
		fdma_info(fdma, "Unable to load FDMA firmware: not present?\n");
		return -EINVAL;
	}

	elfinfo = (struct ELF32_info *)ELF32_initFromMem((uint8_t *)fw->data,
							fw->size, 0);
	if (elfinfo == NULL)
		return -ENOMEM;

	if ((elfinfo->header->e_type != ET_EXEC) ||
	    (elfinfo->header->e_machine != EM_SLIM) ||
	    (elfinfo->header->e_flags != EF_SLIM_FDMA)) {
		res = -ENOMEM;
		goto fail;
	}

	for (i = 0; i < elfinfo->header->e_phnum; i++)
		if (elfinfo->progbase[i].p_type == PT_LOAD) {
			res = fdma_load_segment(fdma, elfinfo, i);
			if (res)
				goto fail;
		}

	ELF32_free(elfinfo);
	fdma_get_hw_revision(fdma, &hw_major, &hw_minor);
	fdma_get_fw_revision(fdma, &fw_major, &fw_minor);
	fdma_info(fdma, "SLIM hw %d.%d, FDMA fw %d.%d\n",
			hw_major, hw_minor, fw_major, fw_minor);

	if (fdma_run_initialise_sequence(fdma) != 0)
		return -ENODEV;

	fdma->firmware_loaded = 1;
	return 1;

fail:
	ELF32_free(elfinfo);
	return res;
}
Exemplo n.º 2
0
static int stm_fdma_fw_request(struct stm_fdma_device *fdev)
{
	const struct firmware *fw = NULL;
	struct ELF32_info *elfinfo = NULL;
	int result = 0;
	int fw_major, fw_minor;
	int hw_major, hw_minor;
	uint8_t *fw_data;

	BUG_ON(!fdev);

	/* Generate FDMA firmware file name */
	result = snprintf(fdev->fw_name, sizeof(fdev->fw_name),
			"fdma_%s_%d.elf", stm_soc(),
			(fdev->fdma_id == -1) ? 0 : fdev->fdma_id);
	BUG_ON(result >= sizeof(fdev->fw_name));

	dev_notice(fdev->dev, "Requesting firmware: %s\n", fdev->fw_name);

	/* Request the FDMA firmware */
	result = request_firmware(&fw, fdev->fw_name, fdev->dev);
	if (result || !fw) {
		dev_err(fdev->dev, "Failed request firmware: not present?\n");
		result = -ENODEV;
		goto error_no_fw;
	}

#ifdef CONFIG_HIBERNATION
	/* Save a copy of the firmware data for future reload */
	fw_data = devm_kzalloc(fdev->dev, fw->size, GFP_KERNEL);
	if (!fw_data) {
		dev_err(fdev->dev, "Cannot allocate memory for firmware\n");
		result = -ENOMEM;
		goto error_elf_init;
	}
	memcpy(fw_data, fw->data, fw->size);
#else
	/* Set pointer to the firmware data */
	fw_data = (uint8_t *) fw->data;
#endif

	/* Initialise firmware as an in-memory ELF file */
	elfinfo = (struct ELF32_info *)ELF32_initFromMem(fw_data, fw->size, 0);
	if (elfinfo == NULL) {
		dev_err(fdev->dev, "Failed to initialise in-memory ELF file\n");
		result = -ENOMEM;
		goto error_elf_init;
	}

	/* Attempt to load the ELF file */
	result = stm_fdma_fw_load(fdev, elfinfo);
	if (result) {
		dev_err(fdev->dev, "Failed to load firmware\n");
		goto error_elf_load;
	}

	/* Retrieve the hardware and firmware versions */
	stm_fdma_hw_get_revisions(fdev, &hw_major, &hw_minor, &fw_major,
			&fw_minor);
	dev_notice(fdev->dev, "SLIM hw %d.%d, FDMA fw %d.%d\n",
			hw_major, hw_minor, fw_major, fw_minor);

	/* Indicate firmware loaded */
	fdev->fw_state = STM_FDMA_FW_STATE_LOADED;

	/* Save pointer to ELF (which points at fw_data) for future reload */
	fdev->fw_elfinfo = elfinfo;

	/* Wake up the wait queue */
	wake_up(&fdev->fw_load_q);

	/* Release the firmware */
	release_firmware(fw);

	return 0;

error_elf_load:
	ELF32_free(elfinfo);
error_elf_init:
	if (fw_data && fw_data != fw->data)
		devm_kfree(fdev->dev, fw_data);
	release_firmware(fw);
error_no_fw:
	fdev->fw_state = STM_FDMA_FW_STATE_ERROR;
	return result;
}