From cf7b4f85c97fcaba290af3de125d7fef0266363f Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Wed, 15 Jun 2022 03:10:35 -0700 Subject: [PATCH] video-driver: Move firmware code out of venus hfi All firmware related code is moved into a firmware file. This is part of cleanup of venus_hfi. Change-Id: Ie915e47644dbbbe73c941488fff6db6e40160b90 Signed-off-by: Stanimir Varbanov --- Kbuild | 1 + driver/vidc/inc/firmware.h | 16 +++ driver/vidc/src/firmware.c | 235 ++++++++++++++++++++++++++++++++++++ driver/vidc/src/venus_hfi.c | 214 ++------------------------------ 4 files changed, 260 insertions(+), 206 deletions(-) create mode 100644 driver/vidc/inc/firmware.h create mode 100644 driver/vidc/src/firmware.c diff --git a/Kbuild b/Kbuild index 48829b6f02..968a7ee391 100644 --- a/Kbuild +++ b/Kbuild @@ -68,6 +68,7 @@ msm_video-objs += driver/vidc/src/msm_vidc_v4l2.o \ driver/vidc/src/msm_vidc_probe.o \ driver/vidc/src/msm_vidc_dt.o \ driver/vidc/src/resources.o \ + driver/vidc/src/firmware.o \ driver/vidc/src/msm_vidc_debug.o \ driver/vidc/src/msm_vidc_memory.o \ driver/vidc/src/msm_vidc_fence.o \ diff --git a/driver/vidc/inc/firmware.h b/driver/vidc/inc/firmware.h new file mode 100644 index 0000000000..07427fd516 --- /dev/null +++ b/driver/vidc/inc/firmware.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022, The Linux Foundation. All rights reserved. + */ + +#ifndef _MSM_VIDC_FIRMWARE_H_ +#define _MSM_VIDC_FIRMWARE_H_ + +struct msm_vidc_core; + +int fw_load(struct msm_vidc_core *core); +int fw_unload(struct msm_vidc_core *core); +int fw_suspend(struct msm_vidc_core *core); +int fw_resume(struct msm_vidc_core *core); + +#endif diff --git a/driver/vidc/src/firmware.c b/driver/vidc/src/firmware.c new file mode 100644 index 0000000000..963eb7a5f3 --- /dev/null +++ b/driver/vidc/src/firmware.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "msm_vidc_core.h" +#include "msm_vidc_debug.h" +#include "msm_vidc_dt.h" +#include "msm_vidc_events.h" +#include "firmware.h" + +#define MAX_FIRMWARE_NAME_SIZE 128 + +struct tzbsp_memprot { + u32 cp_start; + u32 cp_size; + u32 cp_nonpixel_start; + u32 cp_nonpixel_size; +}; + +enum tzbsp_video_state { + TZBSP_VIDEO_STATE_SUSPEND = 0, + TZBSP_VIDEO_STATE_RESUME = 1, + TZBSP_VIDEO_STATE_RESTORE_THRESHOLD = 2, +}; + +static int protect_cp_mem(struct msm_vidc_core *core) +{ + struct tzbsp_memprot memprot; + int rc = 0; + struct context_bank_info *cb; + + if (!core) + return -EINVAL; + + memprot.cp_start = 0x0; + memprot.cp_size = 0x0; + memprot.cp_nonpixel_start = 0x0; + memprot.cp_nonpixel_size = 0x0; + + list_for_each_entry(cb, &core->dt->context_banks, list) { + if (!strcmp(cb->name, "venus_ns")) { + memprot.cp_size = cb->addr_range.start; + + d_vpr_h("%s: memprot.cp_size: %#x\n", + __func__, memprot.cp_size); + } + + if (!strcmp(cb->name, "venus_sec_non_pixel")) { + memprot.cp_nonpixel_start = cb->addr_range.start; + memprot.cp_nonpixel_size = cb->addr_range.size; + + d_vpr_h("%s: cp_nonpixel_start: %#x size: %#x\n", + __func__, memprot.cp_nonpixel_start, + memprot.cp_nonpixel_size); + } + } + + rc = qcom_scm_mem_protect_video_var(memprot.cp_start, memprot.cp_size, + memprot.cp_nonpixel_start, memprot.cp_nonpixel_size); + + if (rc) + d_vpr_e("Failed to protect memory(%d)\n", rc); + + trace_venus_hfi_var_done( + memprot.cp_start, memprot.cp_size, + memprot.cp_nonpixel_start, memprot.cp_nonpixel_size); + + return rc; +} + +static int __load_fw_to_memory(struct platform_device *pdev, + const char *fw_name) +{ + int rc = 0; + const struct firmware *firmware = NULL; + char firmware_name[MAX_FIRMWARE_NAME_SIZE] = { 0 }; + struct device_node *node = NULL; + struct resource res = { 0 }; + phys_addr_t phys = 0; + size_t res_size = 0; + ssize_t fw_size = 0; + void *virt = NULL; + int pas_id = 0; + + if (!fw_name || !(*fw_name) || !pdev) { + d_vpr_e("%s: Invalid inputs\n", __func__); + return -EINVAL; + } + if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) { + d_vpr_e("%s: Invalid fw name\n", __func__); + return -EINVAL; + } + scnprintf(firmware_name, ARRAY_SIZE(firmware_name), "%s.mbn", fw_name); + + rc = of_property_read_u32(pdev->dev.of_node, "pas-id", &pas_id); + if (rc) { + d_vpr_e("%s: failed to read \"pas-id\". error %d\n", + __func__, rc); + goto exit; + } + + node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); + if (!node) { + d_vpr_e("%s: failed to read \"memory-region\"\n", + __func__); + return -EINVAL; + } + + rc = of_address_to_resource(node, 0, &res); + if (rc) { + d_vpr_e("%s: failed to read \"memory-region\", error %d\n", + __func__, rc); + goto exit; + } + phys = res.start; + res_size = (size_t)resource_size(&res); + + rc = request_firmware(&firmware, firmware_name, &pdev->dev); + if (rc) { + d_vpr_e("%s: failed to request fw \"%s\", error %d\n", + __func__, firmware_name, rc); + goto exit; + } + + fw_size = qcom_mdt_get_size(firmware); + if (fw_size < 0 || res_size < (size_t)fw_size) { + rc = -EINVAL; + d_vpr_e("%s: out of bound fw image fw size: %ld, res_size: %lu", + __func__, fw_size, res_size); + goto exit; + } + + virt = memremap(phys, res_size, MEMREMAP_WC); + if (!virt) { + d_vpr_e("%s: failed to remap fw memory phys %pa[p]\n", + __func__, phys); + return -ENOMEM; + } + + /* prevent system suspend during fw_load */ + pm_stay_awake(pdev->dev.parent); + rc = qcom_mdt_load(&pdev->dev, firmware, firmware_name, + pas_id, virt, phys, res_size, NULL); + pm_relax(pdev->dev.parent); + if (rc) { + d_vpr_e("%s: error %d loading fw \"%s\"\n", + __func__, rc, firmware_name); + goto exit; + } + rc = qcom_scm_pas_auth_and_reset(pas_id); + if (rc) { + d_vpr_e("%s: error %d authenticating fw \"%s\"\n", + __func__, rc, firmware_name); + goto exit; + } + + memunmap(virt); + release_firmware(firmware); + d_vpr_h("%s: firmware \"%s\" loaded successfully\n", + __func__, firmware_name); + + return pas_id; + +exit: + if (virt) + memunmap(virt); + if (firmware) + release_firmware(firmware); + + return rc; +} + +int fw_load(struct msm_vidc_core *core) +{ + int rc; + + if (!core->dt->fw_cookie) { + core->dt->fw_cookie = __load_fw_to_memory(core->pdev, + core->dt->fw_name); + if (core->dt->fw_cookie <= 0) { + d_vpr_e("%s: firmware download failed %d\n", + __func__, core->dt->fw_cookie); + core->dt->fw_cookie = 0; + return -ENOMEM; + } + } + + rc = protect_cp_mem(core); + if (rc) { + d_vpr_e("%s: protect memory failed\n", __func__); + goto fail_protect_mem; + } + + return rc; + +fail_protect_mem: + if (core->dt->fw_cookie) + qcom_scm_pas_shutdown(core->dt->fw_cookie); + core->dt->fw_cookie = 0; + return rc; +} + +int fw_unload(struct msm_vidc_core *core) +{ + int ret; + + if (!core->dt->fw_cookie) + return -EINVAL; + + ret = qcom_scm_pas_shutdown(core->dt->fw_cookie); + if (ret) + d_vpr_e("Firmware unload failed rc=%d\n", ret); + + core->dt->fw_cookie = 0; + + return ret; +} + +int fw_suspend(struct msm_vidc_core *core) +{ + return qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0); +} + +int fw_resume(struct msm_vidc_core *core) +{ + return qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_RESUME, 0); +} diff --git a/driver/vidc/src/venus_hfi.c b/driver/vidc/src/venus_hfi.c index 30a792cdd2..1fe5423a9b 100644 --- a/driver/vidc/src/venus_hfi.c +++ b/driver/vidc/src/venus_hfi.c @@ -26,8 +26,7 @@ #include "venus_hfi_response.h" #include "venus_hfi_queue.h" #include "msm_vidc_events.h" - -#define MAX_FIRMWARE_NAME_SIZE 128 +#include "firmware.h" #define update_offset(offset, val) ((offset) += (val)) #define update_timestamp(ts, val) \ @@ -42,19 +41,6 @@ extern struct msm_vidc_core *g_core; static int __resume(struct msm_vidc_core *core); static int __suspend(struct msm_vidc_core *core); -struct tzbsp_memprot { - u32 cp_start; - u32 cp_size; - u32 cp_nonpixel_start; - u32 cp_nonpixel_size; -}; - -enum tzbsp_video_state { - TZBSP_VIDEO_STATE_SUSPEND = 0, - TZBSP_VIDEO_STATE_RESUME = 1, - TZBSP_VIDEO_STATE_RESTORE_THRESHOLD = 2, -}; - /** * Utility function to enforce some of our assumptions. Spam calls to this * in hotspots in code to double check some of the assumptions that we hold. @@ -351,20 +337,6 @@ static void __cancel_power_collapse_work(struct msm_vidc_core *core) cancel_delayed_work(&core->pm_work); } -static int __tzbsp_set_video_state(enum tzbsp_video_state state) -{ - int tzbsp_rsp = qcom_scm_set_remote_state(state, 0); - - d_vpr_l("Set state %d, resp %d\n", state, tzbsp_rsp); - if (tzbsp_rsp) { - d_vpr_e("Failed to set video core state to suspend: %d\n", - tzbsp_rsp); - return -EINVAL; - } - - return 0; -} - static void __flush_debug_queue(struct msm_vidc_core *core, u8 *packet, u32 packet_size) { @@ -571,51 +543,6 @@ skip_power_off: return -EAGAIN; } -static int __protect_cp_mem(struct msm_vidc_core *core) -{ - - struct tzbsp_memprot memprot; - int rc = 0; - struct context_bank_info *cb; - - if (!core) - return -EINVAL; - - memprot.cp_start = 0x0; - memprot.cp_size = 0x0; - memprot.cp_nonpixel_start = 0x0; - memprot.cp_nonpixel_size = 0x0; - - list_for_each_entry(cb, &core->dt->context_banks, list) { - if (!strcmp(cb->name, "venus_ns")) { - memprot.cp_size = cb->addr_range.start; - - d_vpr_h("%s: memprot.cp_size: %#x\n", - __func__, memprot.cp_size); - } - - if (!strcmp(cb->name, "venus_sec_non_pixel")) { - memprot.cp_nonpixel_start = cb->addr_range.start; - memprot.cp_nonpixel_size = cb->addr_range.size; - - d_vpr_h("%s: cp_nonpixel_start: %#x size: %#x\n", - __func__, memprot.cp_nonpixel_start, - memprot.cp_nonpixel_size); - } - } - - rc = qcom_scm_mem_protect_video_var(memprot.cp_start, memprot.cp_size, - memprot.cp_nonpixel_start, memprot.cp_nonpixel_size); - - if (rc) - d_vpr_e("Failed to protect memory(%d)\n", rc); - - trace_venus_hfi_var_done( - memprot.cp_start, memprot.cp_size, - memprot.cp_nonpixel_start, memprot.cp_nonpixel_size); - - return rc; -} #if 0 // TODO static int __core_set_resource(struct msm_vidc_core *core, struct vidc_resource_hdr *resource_hdr, void *resource_value) @@ -874,7 +801,7 @@ static int __suspend(struct msm_vidc_core *core) d_vpr_h("Entering suspend\n"); - rc = __tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND); + rc = fw_suspend(core); if (rc) { d_vpr_e("Failed to suspend video core %d\n", rc); goto err_tzbsp_suspend; @@ -920,7 +847,7 @@ static int __resume(struct msm_vidc_core *core) } /* Reboot the firmware */ - rc = __tzbsp_set_video_state(TZBSP_VIDEO_STATE_RESUME); + rc = fw_resume(core); if (rc) { d_vpr_e("Failed to resume video core %d\n", rc); goto err_set_video_state; @@ -964,7 +891,7 @@ exit: // core->skip_pc_count = 0; return rc; err_reset_core: - __tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND); + fw_suspend(core); err_set_video_state: __venus_power_off(core); err_venus_power_on: @@ -972,108 +899,6 @@ err_venus_power_on: return rc; } -static int __load_fw_to_memory(struct platform_device *pdev, - const char *fw_name) -{ - int rc = 0; - const struct firmware *firmware = NULL; - char firmware_name[MAX_FIRMWARE_NAME_SIZE] = { 0 }; - struct device_node *node = NULL; - struct resource res = { 0 }; - phys_addr_t phys = 0; - size_t res_size = 0; - ssize_t fw_size = 0; - void *virt = NULL; - int pas_id = 0; - - if (!fw_name || !(*fw_name) || !pdev) { - d_vpr_e("%s: Invalid inputs\n", __func__); - return -EINVAL; - } - if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) { - d_vpr_e("%s: Invalid fw name\n", __func__); - return -EINVAL; - } - scnprintf(firmware_name, ARRAY_SIZE(firmware_name), "%s.mbn", fw_name); - - rc = of_property_read_u32(pdev->dev.of_node, "pas-id", &pas_id); - if (rc) { - d_vpr_e("%s: failed to read \"pas-id\". error %d\n", - __func__, rc); - goto exit; - } - - node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); - if (!node) { - d_vpr_e("%s: failed to read \"memory-region\"\n", - __func__); - return -EINVAL; - } - - rc = of_address_to_resource(node, 0, &res); - if (rc) { - d_vpr_e("%s: failed to read \"memory-region\", error %d\n", - __func__, rc); - goto exit; - } - phys = res.start; - res_size = (size_t)resource_size(&res); - - rc = request_firmware(&firmware, firmware_name, &pdev->dev); - if (rc) { - d_vpr_e("%s: failed to request fw \"%s\", error %d\n", - __func__, firmware_name, rc); - goto exit; - } - - fw_size = qcom_mdt_get_size(firmware); - if (fw_size < 0 || res_size < (size_t)fw_size) { - rc = -EINVAL; - d_vpr_e("%s: out of bound fw image fw size: %ld, res_size: %lu", - __func__, fw_size, res_size); - goto exit; - } - - virt = memremap(phys, res_size, MEMREMAP_WC); - if (!virt) { - d_vpr_e("%s: failed to remap fw memory phys %pa[p]\n", - __func__, phys); - return -ENOMEM; - } - - /* prevent system suspend during fw_load */ - pm_stay_awake(pdev->dev.parent); - rc = qcom_mdt_load(&pdev->dev, firmware, firmware_name, - pas_id, virt, phys, res_size, NULL); - pm_relax(pdev->dev.parent); - if (rc) { - d_vpr_e("%s: error %d loading fw \"%s\"\n", - __func__, rc, firmware_name); - goto exit; - } - rc = qcom_scm_pas_auth_and_reset(pas_id); - if (rc) { - d_vpr_e("%s: error %d authenticating fw \"%s\"\n", - __func__, rc, firmware_name); - goto exit; - } - - memunmap(virt); - release_firmware(firmware); - d_vpr_h("%s: firmware \"%s\" loaded successfully\n", - __func__, firmware_name); - - return pas_id; - -exit: - if (virt) - memunmap(virt); - if (firmware) - release_firmware(firmware); - - return rc; -} - int __load_fw(struct msm_vidc_core *core) { const struct msm_vidc_resources_ops *res_ops = core->res_ops; @@ -1097,23 +922,9 @@ int __load_fw(struct msm_vidc_core *core) goto fail_venus_power_on; } - if (!core->dt->fw_cookie) { - core->dt->fw_cookie = __load_fw_to_memory(core->pdev, - core->dt->fw_name); - if (core->dt->fw_cookie <= 0) { - d_vpr_e("%s: firmware download failed %d\n", - __func__, core->dt->fw_cookie); - core->dt->fw_cookie = 0; - rc = -ENOMEM; - goto fail_load_fw; - } - } - - rc = __protect_cp_mem(core); - if (rc) { - d_vpr_e("%s: protect memory failed\n", __func__); - goto fail_protect_mem; - } + rc = fw_load(core); + if (rc) + goto fail_load_fw; /* * Hand off control of regulators to h/w _after_ loading fw. @@ -1125,10 +936,6 @@ int __load_fw(struct msm_vidc_core *core) trace_msm_v4l2_vidc_fw_load("END"); return rc; -fail_protect_mem: - if (core->dt->fw_cookie) - qcom_scm_pas_shutdown(core->dt->fw_cookie); - core->dt->fw_cookie = 0; fail_load_fw: __venus_power_off(core); fail_venus_power_on: @@ -1147,12 +954,7 @@ void __unload_fw(struct msm_vidc_core *core) return; cancel_delayed_work(&core->pm_work); - rc = qcom_scm_pas_shutdown(core->dt->fw_cookie); - if (rc) - d_vpr_e("Firmware unload failed rc=%d\n", rc); - - core->dt->fw_cookie = 0; - + rc = fw_unload(core); __venus_power_off(core); res_ops->put(core);