浏览代码

Merge "msm: camera: icp: Fix FW load sequence issues" into camera-kernel.lnx.5.0

Camera Software Integration 4 年之前
父节点
当前提交
131c340861

+ 4 - 3
drivers/cam_icp/hfi.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/io.h>
@@ -32,8 +32,9 @@
 #define HFI_VERSION_INFO_STEP_BMSK   0xFF
 #define HFI_VERSION_INFO_STEP_SHFT  0
 
-#define HFI_POLL_DELAY_US 100
-#define HFI_POLL_TIMEOUT_US 10000
+/* TO DO Lower timeout value */
+#define HFI_POLL_DELAY_US 10
+#define HFI_POLL_TIMEOUT_US 1500000
 
 static struct hfi_info *g_hfi;
 unsigned int g_icp_mmu_hdl;

+ 10 - 9
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c

@@ -2716,11 +2716,20 @@ static int32_t cam_icp_hw_mgr_cb(void *data, bool recover)
 	return rc;
 }
 
+static void cam_icp_free_fw_mem(void)
+{
+	/* Skip freeing FW memory if not allocated */
+	if (icp_hw_mgr.icp_use_pil)
+		return;
+
+	cam_smmu_dealloc_firmware(icp_hw_mgr.iommu_hdl);
+}
+
 static void cam_icp_free_hfi_mem(void)
 {
 	int rc;
 
-	cam_smmu_dealloc_firmware(icp_hw_mgr.iommu_hdl);
+	cam_icp_free_fw_mem();
 	rc = cam_mem_mgr_free_memory_region(&icp_hw_mgr.hfi_mem.sec_heap);
 	if (rc)
 		CAM_ERR(CAM_ICP, "failed to unreserve sec heap");
@@ -2845,14 +2854,6 @@ 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;

+ 116 - 12
drivers/cam_icp/icp_hw/lx7_hw/lx7_core.c

@@ -15,17 +15,18 @@
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_icp_hw_intf.h"
 #include "hfi_intf.h"
+#include "hfi_sys_defs.h"
 #include "lx7_core.h"
 #include "lx7_reg.h"
 #include "lx7_soc.h"
 
-#define TZ_STATE_RESUME  0
-#define TZ_STATE_SUSPEND 1
-
-#define LX7_FW_NAME "CAMERA_ICP.mdt"
+#define TZ_STATE_SUSPEND 0
+#define TZ_STATE_RESUME  1
 
 #define LX7_GEN_PURPOSE_REG_OFFSET 0x20
 
+#define ICP_FW_NAME_MAX_SIZE    32
+
 static int cam_lx7_ubwc_configure(struct cam_hw_soc_info *soc_info)
 {
 	int i = 0, rc, ddr_type;
@@ -219,6 +220,7 @@ static int cam_lx7_cpas_stop(struct cam_lx7_core_info *core_info)
 int cam_lx7_hw_init(void *priv, void *args, uint32_t arg_size)
 {
 	struct cam_hw_info *lx7 = priv;
+	unsigned long flags;
 	int rc;
 
 	if (!lx7) {
@@ -226,6 +228,13 @@ int cam_lx7_hw_init(void *priv, void *args, uint32_t arg_size)
 		return -EINVAL;
 	}
 
+	spin_lock_irqsave(&lx7->hw_lock, flags);
+	if (lx7->hw_state == CAM_HW_STATE_POWER_UP) {
+		spin_unlock_irqrestore(&lx7->hw_lock, flags);
+		return 0;
+	}
+	spin_unlock_irqrestore(&lx7->hw_lock, flags);
+
 	rc = cam_lx7_cpas_start(lx7->core_info);
 	if (rc)
 		return rc;
@@ -236,6 +245,10 @@ int cam_lx7_hw_init(void *priv, void *args, uint32_t arg_size)
 		goto soc_fail;
 	}
 
+	spin_lock_irqsave(&lx7->hw_lock, flags);
+	lx7->hw_state = CAM_HW_STATE_POWER_UP;
+	spin_unlock_irqrestore(&lx7->hw_lock, flags);
+
 	return 0;
 
 soc_fail:
@@ -246,6 +259,7 @@ soc_fail:
 int cam_lx7_hw_deinit(void *priv, void *args, uint32_t arg_size)
 {
 	struct cam_hw_info *lx7_info = priv;
+	unsigned long flags;
 	int rc;
 
 	if (!lx7_info) {
@@ -253,13 +267,27 @@ int cam_lx7_hw_deinit(void *priv, void *args, uint32_t arg_size)
 		return -EINVAL;
 	}
 
-	rc = cam_lx7_soc_resources_disable(&lx7_info->soc_info);
-	if (rc) {
-		CAM_ERR(CAM_ICP, "failed to disable soc resources rc=%d", rc);
-		return rc;
+	spin_lock_irqsave(&lx7_info->hw_lock, flags);
+	if (lx7_info->hw_state == CAM_HW_STATE_POWER_DOWN) {
+		spin_unlock_irqrestore(&lx7_info->hw_lock, flags);
+		return 0;
 	}
+	spin_unlock_irqrestore(&lx7_info->hw_lock, flags);
+
+	rc = cam_lx7_soc_resources_disable(&lx7_info->soc_info);
+	if (rc)
+		CAM_WARN(CAM_ICP,
+			"failed to disable soc resources rc=%d", rc);
+
+	rc = cam_lx7_cpas_stop(lx7_info->core_info);
+	if (rc)
+		CAM_WARN(CAM_ICP, "cpas stop failed rc=%d", rc);
+
+	spin_lock_irqsave(&lx7_info->hw_lock, flags);
+	lx7_info->hw_state = CAM_HW_STATE_POWER_DOWN;
+	spin_unlock_irqrestore(&lx7_info->hw_lock, flags);
 
-	return cam_lx7_cpas_stop(lx7_info->core_info);
+	return rc;
 }
 
 static void prepare_boot(struct cam_hw_info *lx7_info,
@@ -288,7 +316,9 @@ static void prepare_shutdown(struct cam_hw_info *lx7_info)
 #if IS_REACHABLE(CONFIG_QCOM_MDT_LOADER)
 static int __load_firmware(struct platform_device *pdev)
 {
+	const char *fw_name;
 	const struct firmware *firmware = NULL;
+	char firmware_name[ICP_FW_NAME_MAX_SIZE] = {0};
 	void *vaddr = NULL;
 	struct device_node *node;
 	struct resource res;
@@ -297,6 +327,27 @@ static int __load_firmware(struct platform_device *pdev)
 	ssize_t fw_size;
 	int rc;
 
+	if (!pdev) {
+		CAM_ERR(CAM_ICP, "invalid args");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_string(pdev->dev.of_node, "fw_name",
+		&fw_name);
+	if (rc) {
+		CAM_ERR(CAM_ICP, "FW image name not found");
+		return rc;
+	}
+
+	/* Account for ".mdt" size [4 characters] */
+	if (strlen(fw_name) >= (ICP_FW_NAME_MAX_SIZE - 4)) {
+		CAM_ERR(CAM_ICP, "Invalid fw name %s", fw_name);
+		return -EINVAL;
+	}
+
+	scnprintf(firmware_name, ARRAY_SIZE(firmware_name),
+		"%s.mdt", fw_name);
+
 	node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
 	if (!node) {
 		CAM_ERR(CAM_ICP, "firmware memory region not found");
@@ -313,11 +364,11 @@ static int __load_firmware(struct platform_device *pdev)
 	res_start = res.start;
 	res_size = (size_t)resource_size(&res);
 
-	rc = request_firmware(&firmware, LX7_FW_NAME, &pdev->dev);
+	rc = request_firmware(&firmware, firmware_name, &pdev->dev);
 	if (rc) {
 		CAM_ERR(CAM_ICP,
 			"error requesting %s firmware rc=%d",
-			LX7_FW_NAME, rc);
+			firmware_name, rc);
 		return rc;
 	}
 
@@ -338,7 +389,7 @@ static int __load_firmware(struct platform_device *pdev)
 		goto out;
 	}
 
-	rc = qcom_mdt_load(&pdev->dev, firmware, LX7_FW_NAME, CAM_FW_PAS_ID,
+	rc = qcom_mdt_load(&pdev->dev, firmware, firmware_name, CAM_FW_PAS_ID,
 			vaddr, res_start, res_size, NULL);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "failed to load firmware rc=%d", rc);
@@ -416,6 +467,47 @@ static int set_remote_state(uint32_t state)
 	return rc;
 }
 
+static int __cam_lx7_update_clk_rate(
+	struct cam_hw_info *lx7_info,
+	int32_t *clk_lvl)
+{
+	int32_t clk_level = 0, rc;
+	struct cam_ahb_vote       ahb_vote;
+	struct cam_lx7_core_info *core_info = NULL;
+	struct cam_hw_soc_info   *soc_info = NULL;
+
+	if (!clk_lvl) {
+		CAM_ERR(CAM_ICP, "Invalid args");
+		return -EINVAL;
+	}
+
+	soc_info = &lx7_info->soc_info;
+	core_info = lx7_info->core_info;
+	if (!core_info || !soc_info) {
+		CAM_ERR(CAM_ICP, "Invalid args");
+		return -EINVAL;
+	}
+
+	clk_level = *((int32_t *)clk_lvl);
+	CAM_DBG(CAM_ICP,
+		"Update ICP clock to level [%d]", clk_level);
+	rc = cam_lx7_update_clk_rate(soc_info, clk_level);
+	if (rc)
+		CAM_WARN(CAM_ICP,
+			"Failed to update clk to level: %d rc: %d",
+			clk_level, rc);
+
+	ahb_vote.type = CAM_VOTE_ABSOLUTE;
+	ahb_vote.vote.level = clk_level;
+	rc = cam_cpas_update_ahb_vote(
+		core_info->cpas_handle, &ahb_vote);
+	if (rc)
+		CAM_WARN(CAM_ICP,
+			"Failed to update ahb vote rc: %d", rc);
+
+	return rc;
+}
+
 int cam_lx7_process_cmd(void *priv, uint32_t cmd_type,
 			void *args, uint32_t arg_size)
 {
@@ -452,6 +544,18 @@ int cam_lx7_process_cmd(void *priv, uint32_t cmd_type,
 	case CAM_ICP_CMD_UBWC_CFG:
 		rc = cam_lx7_ubwc_configure(&lx7_info->soc_info);
 		break;
+	case CAM_ICP_SEND_INIT:
+		hfi_send_system_cmd(HFI_CMD_SYS_INIT, 0, 0);
+		rc = 0;
+		break;
+	case CAM_ICP_CMD_PC_PREP:
+		hfi_send_system_cmd(HFI_CMD_SYS_PC_PREP, 0, 0);
+		rc = 0;
+		break;
+	case CAM_ICP_CMD_CLK_UPDATE: {
+		rc = __cam_lx7_update_clk_rate(lx7_info, args);
+		break;
+	}
 	default:
 		CAM_ERR(CAM_ICP, "invalid command type=%u", cmd_type);
 		break;

+ 44 - 0
drivers/cam_icp/icp_hw/lx7_hw/lx7_soc.c

@@ -138,3 +138,47 @@ int cam_lx7_soc_resources_disable(struct cam_hw_soc_info *soc_info)
 
 	return rc;
 }
+
+int cam_lx7_update_clk_rate(struct cam_hw_soc_info *soc_info,
+	int32_t clk_level)
+{
+	int32_t src_clk_idx = 0;
+	int32_t clk_rate = 0;
+
+	if (!soc_info) {
+		CAM_ERR(CAM_ICP, "Invalid args");
+		return -EINVAL;
+	}
+
+	if ((clk_level < 0) || (clk_level >= CAM_MAX_VOTE)) {
+		CAM_ERR(CAM_ICP, "clock level %d is not valid",
+			clk_level);
+		return -EINVAL;
+	}
+
+	if (!soc_info->clk_level_valid[clk_level]) {
+		CAM_ERR(CAM_ICP,
+			"Clock level %d not supported",
+			clk_level);
+		return -EINVAL;
+	}
+
+	src_clk_idx = soc_info->src_clk_idx;
+	if ((src_clk_idx < 0) || (src_clk_idx >= CAM_SOC_MAX_CLK)) {
+		CAM_WARN(CAM_ICP, "src_clk not defined for %s",
+			soc_info->dev_name);
+		return -EINVAL;
+	}
+
+	clk_rate = soc_info->clk_rate[clk_level][src_clk_idx];
+	if ((soc_info->clk_level_valid[CAM_TURBO_VOTE]) &&
+		(soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) &&
+		(clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) {
+		CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d",
+			clk_rate,
+			soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]);
+		clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
+	}
+
+	return cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
+}

+ 2 - 0
drivers/cam_icp/icp_hw/lx7_hw/lx7_soc.h

@@ -28,5 +28,7 @@ int cam_lx7_soc_resources_deinit(struct cam_hw_soc_info *soc_info);
 
 int cam_lx7_soc_resources_enable(struct cam_hw_soc_info *soc_info);
 int cam_lx7_soc_resources_disable(struct cam_hw_soc_info *soc_info);
+int cam_lx7_update_clk_rate(struct cam_hw_soc_info *soc_info,
+	int32_t clk_level);
 
 #endif /* _CAM_LX7_SOC_H_ */