linux/drivers/media/platform/qcom/iris/iris_firmware.c
Vikash Garodia dff99dff6c media: iris: Add support for multiple TZ content protection(CP) configs
vpu4 needs an additional configuration with respect to CP regions. Make
the CP configuration as array such that the multiple configuration can be
managed per platform.

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Co-developed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Reviewed-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
2026-01-20 16:22:24 +01:00

113 lines
2.7 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/firmware.h>
#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/of_address.h>
#include <linux/of_reserved_mem.h>
#include <linux/soc/qcom/mdt_loader.h>
#include "iris_core.h"
#include "iris_firmware.h"
#define MAX_FIRMWARE_NAME_SIZE 128
static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
{
u32 pas_id = core->iris_platform_data->pas_id;
const struct firmware *firmware = NULL;
struct device *dev = core->dev;
struct resource res;
phys_addr_t mem_phys;
size_t res_size;
ssize_t fw_size;
void *mem_virt;
int ret;
if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4)
return -EINVAL;
ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res);
if (ret)
return ret;
mem_phys = res.start;
res_size = resource_size(&res);
ret = request_firmware(&firmware, fw_name, dev);
if (ret)
return ret;
fw_size = qcom_mdt_get_size(firmware);
if (fw_size < 0 || res_size < (size_t)fw_size) {
ret = -EINVAL;
goto err_release_fw;
}
mem_virt = memremap(mem_phys, res_size, MEMREMAP_WC);
if (!mem_virt) {
ret = -ENOMEM;
goto err_release_fw;
}
ret = qcom_mdt_load(dev, firmware, fw_name,
pas_id, mem_virt, mem_phys, res_size, NULL);
memunmap(mem_virt);
err_release_fw:
release_firmware(firmware);
return ret;
}
int iris_fw_load(struct iris_core *core)
{
const struct tz_cp_config *cp_config;
const char *fwpath = NULL;
int i, ret;
ret = of_property_read_string_index(core->dev->of_node, "firmware-name", 0,
&fwpath);
if (ret)
fwpath = core->iris_platform_data->fwname;
ret = iris_load_fw_to_memory(core, fwpath);
if (ret) {
dev_err(core->dev, "firmware download failed\n");
return -ENOMEM;
}
ret = qcom_scm_pas_auth_and_reset(core->iris_platform_data->pas_id);
if (ret) {
dev_err(core->dev, "auth and reset failed: %d\n", ret);
return ret;
}
for (i = 0; i < core->iris_platform_data->tz_cp_config_data_size; i++) {
cp_config = &core->iris_platform_data->tz_cp_config_data[i];
ret = qcom_scm_mem_protect_video_var(cp_config->cp_start,
cp_config->cp_size,
cp_config->cp_nonpixel_start,
cp_config->cp_nonpixel_size);
if (ret) {
dev_err(core->dev, "qcom_scm_mem_protect_video_var failed: %d\n", ret);
qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
return ret;
}
}
return ret;
}
int iris_fw_unload(struct iris_core *core)
{
return qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
}
int iris_set_hw_state(struct iris_core *core, bool resume)
{
return qcom_scm_set_remote_state(resume, 0);
}