瀏覽代碼

msm: vidc: Use upstream api to load firmware image

Use upstream compliant APIs to, load and authenticate firmware image.
Downstream api, PIL/SSR, are deprecated.

Change-Id: I121c3c0276cdd84fa18ff8f65df45b3ac00e7443
Signed-off-by: Akshata Sahukar <[email protected]>
Signed-off-by: Chinmay Sawarkar <[email protected]>
Akshata Sahukar 5 年之前
父節點
當前提交
9099609e92
共有 2 個文件被更改,包括 120 次插入13 次删除
  1. 1 1
      driver/vidc/inc/msm_vidc_dt.h
  2. 119 12
      driver/vidc/src/venus_hfi.c

+ 1 - 1
driver/vidc/inc/msm_vidc_dt.h

@@ -218,7 +218,7 @@ struct msm_vidc_dt {
 	struct list_head context_banks;
 	struct mutex cb_lock;
 	const char *fw_name;
-	void *fw_cookie;
+	int fw_cookie;
 };
 
 int msm_vidc_init_dt(struct platform_device *pdev);

+ 119 - 12
driver/vidc/src/venus_hfi.c

@@ -13,6 +13,10 @@
 #include <linux/reset.h>
 #include <linux/interconnect.h>
 #include <soc/qcom/subsystem_restart.h>
+#include <linux/of_address.h>
+#include <linux/firmware.h>
+#include <linux/qcom_scm.h>
+#include <linux/soc/qcom/mdt_loader.h>
 
 #include "venus_hfi.h"
 #include "msm_vidc_core.h"
@@ -27,6 +31,8 @@
 
 #define MIN_PAYLOAD_SIZE 3
 
+#define MAX_FIRMWARE_NAME_SIZE 128
+
 static int __resume(struct msm_vidc_core *core);
 static int __suspend(struct msm_vidc_core *core);
 
@@ -2246,13 +2252,112 @@ fail_alloc_queue:
 	return -ENOMEM;
 }
 
+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.mdt", 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__, rc, firmware_name);
+		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;
+	}
+
+	rc = qcom_mdt_load(&pdev->dev, firmware, firmware_name,
+		pas_id, virt, phys, res_size, NULL);
+	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;
+}
+
 static int __load_fw(struct msm_vidc_core *core)
 {
 	int rc = 0;
 
 	rc = __init_resources(core);
 	if (rc) {
-		d_vpr_e("Failed to init resources: %d\n", rc);
+		d_vpr_e("%s: Failed to init resources: %d\n", __func__, rc);
 		goto fail_init_res;
 	}
 
@@ -2263,11 +2368,12 @@ static int __load_fw(struct msm_vidc_core *core)
 	}
 
 	if (!core->dt->fw_cookie) {
-		core->dt->fw_cookie = subsystem_get_with_fwname("venus",
-								core->dt->fw_name);
-		if (IS_ERR_OR_NULL(core->dt->fw_cookie)) {
-			d_vpr_e("%s: firmware download failed\n", __func__);
-			core->dt->fw_cookie = NULL;
+		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;
 		}
@@ -2284,14 +2390,13 @@ static int __load_fw(struct msm_vidc_core *core)
 	* (s/w triggered) to fast (HW triggered) unless the h/w vote is
 	* present.
 	*/
-	if (__enable_hw_power_collapse(core))
-		d_vpr_e("%s: hardware power collapse unsuccessful\n", __func__);
+	__enable_hw_power_collapse(core);
 
 	return rc;
 fail_protect_mem:
 	if (core->dt->fw_cookie)
-		subsystem_put(core->dt->fw_cookie);
-	core->dt->fw_cookie = NULL;
+		qcom_scm_pas_shutdown(core->dt->fw_cookie);
+	core->dt->fw_cookie = 0;
 fail_load_fw:
 	call_venus_op(core, power_off, core);
 fail_venus_power_on:
@@ -2309,10 +2414,12 @@ static void __unload_fw(struct msm_vidc_core *core)
 	if (core->state != MSM_VIDC_CORE_DEINIT)
 		flush_workqueue(core->pm_workq);
 
-	subsystem_put(core->dt->fw_cookie);
+	qcom_scm_pas_shutdown(core->dt->fw_cookie);
+	core->dt->fw_cookie = 0;
+
 	__interface_queues_release(core);
 	call_venus_op(core, power_off, core);
-	core->dt->fw_cookie = NULL;
+
 	__deinit_resources(core);
 
 	d_vpr_h("Firmware unloaded successfully\n");