فهرست منبع

Merge "msm: camera: icp: Enable full LX7 boot/load sequence" into camera-kernel.lnx.5.0

Camera Software Integration 4 سال پیش
والد
کامیت
42c032daea

+ 19 - 4
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c

@@ -2826,6 +2826,9 @@ static int cam_icp_allocate_fw_mem(void)
 	size_t len;
 	dma_addr_t iova;
 
+	if (icp_hw_mgr.icp_use_pil)
+		return 0;
+
 	rc = cam_smmu_alloc_firmware(icp_hw_mgr.iommu_hdl,
 		&iova, &kvaddr, &len);
 	if (rc)
@@ -2842,6 +2845,14 @@ static int cam_icp_allocate_fw_mem(void)
 	return rc;
 }
 
+static void cam_icp_free_fw_mem(void)
+{
+	if (icp_hw_mgr.icp_use_pil)
+		return;
+
+	cam_smmu_dealloc_firmware(icp_hw_mgr.iommu_hdl);
+}
+
 static int cam_icp_allocate_qdss_mem(void)
 {
 	int rc;
@@ -2966,7 +2977,7 @@ cmd_q_alloc_failed:
 qtbl_alloc_failed:
 	cam_smmu_dealloc_qdss(icp_hw_mgr.iommu_hdl);
 fw_alloc_failed:
-	cam_smmu_dealloc_firmware(icp_hw_mgr.iommu_hdl);
+	cam_icp_free_fw_mem();
 	return rc;
 }
 
@@ -3166,9 +3177,12 @@ static int cam_icp_mgr_proc_boot(struct cam_icp_hw_mgr *hw_mgr)
 		return -EINVAL;
 	}
 
-	args.firmware.iova = hw_mgr->hfi_mem.fw_buf.iova;
-	args.firmware.kva = hw_mgr->hfi_mem.fw_buf.kva;
-	args.firmware.len = hw_mgr->hfi_mem.fw_buf.len;
+	if (!hw_mgr->icp_use_pil) {
+		/* We handle the iommu mapping */
+		args.firmware.iova = hw_mgr->hfi_mem.fw_buf.iova;
+		args.firmware.kva = hw_mgr->hfi_mem.fw_buf.kva;
+		args.firmware.len = hw_mgr->hfi_mem.fw_buf.len;
+	}
 
 	args.irq_cb.data = hw_mgr;
 	args.irq_cb.cb = cam_icp_hw_mgr_cb;
@@ -5964,6 +5978,7 @@ static int cam_icp_mgr_alloc_devs(struct device_node *np)
 
 	icp_hw_mgr.ipe_bps_pc_flag = of_property_read_bool(np, "ipe_bps_pc_en");
 	icp_hw_mgr.icp_pc_flag = of_property_read_bool(np, "icp_pc_en");
+	icp_hw_mgr.icp_use_pil = of_property_read_bool(np, "icp_use_pil");
 
 	return 0;
 

+ 2 - 0
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h

@@ -338,6 +338,7 @@ struct cam_icp_clk_info {
  * @icp_pc_flag: Flag to enable/disable power collapse
  * @ipe_bps_pc_flag: Flag to enable/disable
  *                   power collapse for ipe & bps
+ * @icp_use_pil: Flag to indicate usage of PIL framework
  * @icp_debug_clk: Set clock based on debug value
  * @icp_default_clk: Set this clok if user doesn't supply
  * @clk_info: Clock info of hardware
@@ -388,6 +389,7 @@ struct cam_icp_hw_mgr {
 	struct dentry *dentry;
 	bool icp_pc_flag;
 	bool ipe_bps_pc_flag;
+	bool icp_use_pil;
 	uint64_t icp_debug_clk;
 	uint64_t icp_default_clk;
 	struct cam_icp_clk_info clk_info[ICP_CLK_HW_MAX];

+ 153 - 4
drivers/cam_icp/icp_hw/lx7_hw/lx7_core.c

@@ -6,6 +6,7 @@
 #include <linux/firmware.h>
 #include <linux/of_address.h>
 #include <linux/qcom_scm.h>
+#include <linux/soc/qcom/mdt_loader.h>
 
 #include "cam_cpas_api.h"
 #include "cam_debug_util.h"
@@ -21,7 +22,7 @@
 #define TZ_STATE_RESUME  0
 #define TZ_STATE_SUSPEND 1
 
-#define LX7_FW_NAME "CAMERA_ICP.elf"
+#define LX7_FW_NAME "CAMERA_ICP.mdt"
 
 #define LX7_GEN_PURPOSE_REG_OFFSET 0x20
 
@@ -261,7 +262,149 @@ int cam_lx7_hw_deinit(void *priv, void *args, uint32_t arg_size)
 	return cam_lx7_cpas_stop(lx7_info->core_info);
 }
 
-static int __tz_set_icp_state(uint32_t state)
+static void prepare_boot(struct cam_hw_info *lx7_info,
+			struct cam_icp_boot_args *args)
+{
+	struct cam_lx7_core_info *core_info = lx7_info->core_info;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lx7_info->hw_lock, flags);
+	core_info->irq_cb.data = args->irq_cb.data;
+	core_info->irq_cb.cb = args->irq_cb.cb;
+	spin_unlock_irqrestore(&lx7_info->hw_lock, flags);
+}
+
+static void prepare_shutdown(struct cam_hw_info *lx7_info)
+{
+	struct cam_lx7_core_info *core_info = lx7_info->core_info;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lx7_info->hw_lock, flags);
+	core_info->irq_cb.data = NULL;
+	core_info->irq_cb.cb = NULL;
+	spin_unlock_irqrestore(&lx7_info->hw_lock, flags);
+}
+
+#if IS_REACHABLE(CONFIG_QCOM_MDT_LOADER)
+static int __load_firmware(struct platform_device *pdev)
+{
+	const struct firmware *firmware = NULL;
+	void *vaddr = NULL;
+	struct device_node *node;
+	struct resource res;
+	phys_addr_t res_start;
+	size_t res_size;
+	ssize_t fw_size;
+	int rc;
+
+	node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
+	if (!node) {
+		CAM_ERR(CAM_ICP, "firmware memory region not found");
+		return -ENODEV;
+	}
+
+	rc = of_address_to_resource(node, 0, &res);
+	of_node_put(node);
+	if (rc) {
+		CAM_ERR(CAM_ICP, "missing firmware resource address rc=%d", rc);
+		return rc;
+	}
+
+	res_start = res.start;
+	res_size = (size_t)resource_size(&res);
+
+	rc = request_firmware(&firmware, LX7_FW_NAME, &pdev->dev);
+	if (rc) {
+		CAM_ERR(CAM_ICP,
+			"error requesting %s firmware rc=%d",
+			LX7_FW_NAME, rc);
+		return rc;
+	}
+
+	/* Make sure carveout and binary sizes are compatible */
+	fw_size = qcom_mdt_get_size(firmware);
+	if (fw_size < 0 || res_size < (size_t)fw_size) {
+		CAM_ERR(CAM_ICP,
+			"carveout[sz=%zu] not big enough for firmware[sz=%zd]",
+			res_size, fw_size);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	vaddr = ioremap_wc(res_start, res_size);
+	if (!vaddr) {
+		CAM_ERR(CAM_ICP, "unable to map firmware carveout");
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = qcom_mdt_load(&pdev->dev, firmware, LX7_FW_NAME, CAM_FW_PAS_ID,
+			vaddr, res_start, res_size, NULL);
+	if (rc) {
+		CAM_ERR(CAM_ICP, "failed to load firmware rc=%d", rc);
+		goto out;
+	}
+
+out:
+	if (vaddr)
+		iounmap(vaddr);
+
+	release_firmware(firmware);
+	return rc;
+}
+#endif
+
+static int cam_lx7_boot(struct cam_hw_info *lx7_info,
+			struct cam_icp_boot_args *args,
+			uint32_t arg_size)
+{
+	int rc;
+
+	if (!IS_REACHABLE(CONFIG_QCOM_MDT_LOADER))
+		return -EOPNOTSUPP;
+
+	if (!lx7_info || !args) {
+		CAM_ERR(CAM_ICP,
+			"invalid args: lx7_info=%pK args=%pK",
+			lx7_info, args);
+		return -EINVAL;
+	}
+
+	if (arg_size != sizeof(struct cam_icp_boot_args)) {
+		CAM_ERR(CAM_ICP, "invalid boot args size");
+		return -EINVAL;
+	}
+
+	prepare_boot(lx7_info, args);
+
+#if IS_REACHABLE(CONFIG_QCOM_MDT_LOADER)
+	rc = __load_firmware(lx7_info->soc_info.pdev);
+	if (rc) {
+		CAM_ERR(CAM_ICP, "firmware loading failed rc=%d", rc);
+		goto err;
+	}
+#endif
+
+	rc = qcom_scm_pas_auth_and_reset(CAM_FW_PAS_ID);
+	if (rc) {
+		CAM_ERR(CAM_ICP, "auth and reset failed rc=%d", rc);
+		goto err;
+	}
+
+	return 0;
+err:
+	prepare_shutdown(lx7_info);
+	return rc;
+}
+
+static int cam_lx7_shutdown(struct cam_hw_info *lx7_info)
+{
+	prepare_shutdown(lx7_info);
+
+	return qcom_scm_pas_shutdown(CAM_FW_PAS_ID);
+}
+
+static int set_remote_state(uint32_t state)
 {
 	int rc;
 
@@ -285,11 +428,17 @@ int cam_lx7_process_cmd(void *priv, uint32_t cmd_type,
 	}
 
 	switch (cmd_type) {
+	case CAM_ICP_CMD_PROC_SHUTDOWN:
+		rc = cam_lx7_shutdown(lx7_info);
+		break;
+	case CAM_ICP_CMD_PROC_BOOT:
+		rc = cam_lx7_boot(lx7_info, args, arg_size);
+		break;
 	case CAM_ICP_CMD_POWER_COLLAPSE:
-		rc = __tz_set_icp_state(TZ_STATE_SUSPEND);
+		rc = set_remote_state(TZ_STATE_SUSPEND);
 		break;
 	case CAM_ICP_CMD_POWER_RESUME:
-		rc = __tz_set_icp_state(TZ_STATE_RESUME);
+		rc = set_remote_state(TZ_STATE_RESUME);
 		break;
 	case CAM_ICP_CMD_VOTE_CPAS:
 		rc = cam_lx7_cpas_vote(lx7_info->core_info, args);

+ 1 - 2
drivers/cam_icp/icp_hw/lx7_hw/lx7_core.h

@@ -12,9 +12,8 @@
 #define LX7_CSR_BASE  0
 #define LX7_CIRQ_BASE 1
 
-/* TODO: Update once we're ready to use TZ */
 #define UNSUPPORTED_PROC_PAS_ID   30
-#define CAM_FW_PAS_ID             UNSUPPORTED_PROC_PAS_ID
+#define CAM_FW_PAS_ID             33
 
 struct cam_lx7_core_info {
 	struct cam_icp_irq_cb irq_cb;