Răsfoiți Sursa

msm: camera: icp: hfi adaptation for presil mode

Added pre-sil implementation of icp hfi.
Hfi functions need to modify shared queue memory shared with FW
at byte level and frequently. Hence we redirect hfi function calls
to PCHost and have queue logic running directly on PCHost.

CRs-Fixed: 2932495
Change-Id: Ib3b92f998e5836b27573a2756f94f170d2827c82
Signed-off-by: Suraj Dongre <[email protected]>
Suraj Dongre 4 ani în urmă
părinte
comite
a4899090dc

+ 123 - 2
drivers/cam_icp/hfi.c

@@ -12,6 +12,7 @@
 #include <media/cam_icp.h>
 #include <linux/iopoll.h>
 
+#include "cam_presil_hw_access.h"
 #include "cam_io_util.h"
 #include "hfi_reg.h"
 #include "hfi_sys_defs.h"
@@ -20,6 +21,7 @@
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_debug_util.h"
 #include "cam_compat.h"
+#include "cam_soc_util.h"
 
 #define HFI_VERSION_INFO_MAJOR_VAL  1
 #define HFI_VERSION_INFO_MINOR_VAL  1
@@ -42,11 +44,16 @@ unsigned int g_icp_mmu_hdl;
 static DEFINE_MUTEX(hfi_cmd_q_mutex);
 static DEFINE_MUTEX(hfi_msg_q_mutex);
 
+static int cam_hfi_presil_setup(struct hfi_mem_info *hfi_mem);
+static int cam_hfi_presil_set_init_request(void);
+
+#ifndef CONFIG_CAM_PRESIL
 static void hfi_irq_raise(struct hfi_info *hfi)
 {
 	if (hfi->ops.irq_raise)
 		hfi->ops.irq_raise(hfi->priv);
 }
+#endif
 
 static void hfi_irq_enable(struct hfi_info *hfi)
 {
@@ -162,6 +169,7 @@ void cam_hfi_queue_dump(void)
 	hfi_queue_dump(dwords, num_dwords);
 }
 
+#ifndef CONFIG_CAM_PRESIL
 int hfi_write_cmd(void *cmd_ptr)
 {
 	uint32_t size_in_words, empty_space, new_write_idx, read_idx, temp;
@@ -348,6 +356,7 @@ err:
 	mutex_unlock(&hfi_msg_q_mutex);
 	return rc;
 }
+#endif /* #ifndef CONFIG_CAM_PRESIL */
 
 int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg)
 {
@@ -932,8 +941,6 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops,
 		icp_base + HFI_REG_FWUNCACHED_REGION_IOVA);
 	cam_io_w_mb((uint32_t)hfi_mem->fw_uncached.len,
 		icp_base + HFI_REG_FWUNCACHED_REGION_SIZE);
-	cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_SET,
-		icp_base + HFI_REG_HOST_ICP_INIT_REQUEST);
 
 	CAM_DBG(CAM_HFI, "IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]",
 		hfi_mem->io_mem.iova, hfi_mem->io_mem.len,
@@ -951,6 +958,15 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops,
 		hfi_mem->qtbl.iova, hfi_mem->qtbl.len,
 		hfi_mem->sfr_buf.iova, hfi_mem->sfr_buf.len);
 
+	if (cam_presil_mode_enabled())
+		cam_hfi_presil_setup(hfi_mem);
+
+	cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_SET,
+		icp_base + HFI_REG_HOST_ICP_INIT_REQUEST);
+
+	if (cam_presil_mode_enabled())
+		cam_hfi_presil_set_init_request();
+
 	if (cam_common_read_poll_timeout(icp_base +
 		    HFI_REG_ICP_HOST_INIT_RESPONSE,
 		    HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US,
@@ -985,6 +1001,11 @@ alloc_fail:
 
 void cam_hfi_deinit(void)
 {
+	if (cam_presil_mode_enabled()) {
+		CAM_DBG(CAM_HFI, "SYS_RESET Needed in presil for back to back hfi_init success");
+		hfi_send_system_cmd(HFI_CMD_SYS_RESET, 0, 0);
+	}
+
 	mutex_lock(&hfi_cmd_q_mutex);
 	mutex_lock(&hfi_msg_q_mutex);
 
@@ -1003,3 +1024,103 @@ err:
 	mutex_unlock(&hfi_cmd_q_mutex);
 	mutex_unlock(&hfi_msg_q_mutex);
 }
+
+
+#ifdef CONFIG_CAM_PRESIL
+static int cam_hfi_presil_setup(struct hfi_mem_info *hfi_mem)
+{
+	/**
+	 * The pchost maintains its own set of queue structures and
+	 * needs additional info to accomplish this. Use the set of
+	 * dummy registers to pass along this info.
+	 */
+	/**
+	 * IOVA region length for each queue is currently hardcoded in
+	 * pchost (except for SFR). No need to send for now.
+	 */
+	cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_CMD_Q_IOVA, hfi_mem->cmd_q.iova);
+	cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_MSG_Q_IOVA, hfi_mem->msg_q.iova);
+	cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_DBG_Q_IOVA, hfi_mem->dbg_q.iova);
+	cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_SFR_LEN, hfi_mem->sfr_buf.len);
+
+	return 0;
+}
+
+static int cam_hfi_presil_set_init_request(void)
+{
+	CAM_DBG(CAM_PRESIL, "notifying pchost to start HFI init...");
+	cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_A5_HW_VERSION_TO_START_HFI_INIT, 0xFF);
+	CAM_DBG(CAM_PRESIL, "got done with PCHOST HFI init...");
+
+	return 0;
+}
+
+int hfi_write_cmd(void *cmd_ptr)
+{
+	int presil_rc = CAM_PRESIL_BLOCKED;
+	int rc = 0;
+
+	if (!cmd_ptr) {
+		CAM_ERR(CAM_HFI, "command is null");
+		return -EINVAL;
+	}
+
+	mutex_lock(&hfi_cmd_q_mutex);
+
+	presil_rc = cam_presil_hfi_write_cmd(cmd_ptr, (*(uint32_t *)cmd_ptr));
+
+	if ((presil_rc != CAM_PRESIL_SUCCESS) && (presil_rc != CAM_PRESIL_BLOCKED)) {
+		CAM_ERR(CAM_HFI, "failed presil rc %d", presil_rc);
+		rc = -EINVAL;
+	} else {
+		CAM_DBG(CAM_HFI, "presil rc %d", presil_rc);
+	}
+
+	mutex_unlock(&hfi_cmd_q_mutex);
+	return rc;
+}
+
+int hfi_read_message(uint32_t *pmsg, uint8_t q_id,
+	uint32_t *words_read)
+{
+	int presil_rc = CAM_PRESIL_BLOCKED;
+	int rc = 0;
+
+	if (!pmsg) {
+		CAM_ERR(CAM_HFI, "Invalid msg");
+		return -EINVAL;
+	}
+
+	if (q_id > Q_DBG) {
+		CAM_ERR(CAM_HFI, "Invalid q :%u", q_id);
+		return -EINVAL;
+	}
+	mutex_lock(&hfi_msg_q_mutex);
+
+	memset(pmsg, 0x0, sizeof(uint32_t) * 256 /* ICP_MSG_BUF_SIZE */);
+	*words_read = 0;
+
+	presil_rc = cam_presil_hfi_read_message(pmsg, q_id, words_read);
+
+	if ((presil_rc != CAM_PRESIL_SUCCESS) && (presil_rc != CAM_PRESIL_BLOCKED)) {
+		CAM_ERR(CAM_HFI, "failed presil rc %d", presil_rc);
+		rc = -EINVAL;
+	} else {
+		CAM_DBG(CAM_HFI, "presil rc %d", presil_rc);
+	}
+
+	mutex_unlock(&hfi_msg_q_mutex);
+	return rc;
+}
+#else
+/* when presil mode not enabled */
+static int cam_hfi_presil_setup(struct hfi_mem_info *hfi_mem)
+{
+	return 0;
+}
+
+static int cam_hfi_presil_set_init_request(void)
+{
+	return 0;
+}
+#endif /* #ifdef CONFIG_CAM_PRESIL */

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

@@ -4064,6 +4064,11 @@ static int cam_icp_mgr_hw_open_u(void *hw_mgr_priv, void *download_fw_args)
 		return 0;
 	}
 
+	if (cam_presil_mode_enabled()) {
+		CAM_DBG(CAM_PRESIL, "hw_open from umd skipped for presil");
+		return 0;
+	}
+
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
 	rc = cam_icp_mgr_hw_open(hw_mgr, download_fw_args);
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
@@ -4074,13 +4079,17 @@ static int cam_icp_mgr_hw_open_u(void *hw_mgr_priv, void *download_fw_args)
 static int cam_icp_mgr_hw_open_k(void *hw_mgr_priv, void *download_fw_args)
 {
 	struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv;
+	int rc;
 
 	if (!hw_mgr) {
 		CAM_ERR(CAM_ICP, "Null hw mgr");
 		return 0;
 	}
 
-	return cam_icp_mgr_hw_open(hw_mgr, download_fw_args);
+	rc = cam_icp_mgr_hw_open(hw_mgr, download_fw_args);
+	CAM_DBG(CAM_ICP, "hw_open from kmd done %d", rc);
+
+	return rc;
 }
 
 static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr)

+ 15 - 0
drivers/cam_icp/icp_hw/lx7_hw/lx7_core.c

@@ -21,6 +21,7 @@
 #include "lx7_soc.h"
 #include "cam_common_util.h"
 #include "cam_compat.h"
+#include "cam_presil_hw_access.h"
 
 #define TZ_STATE_SUSPEND 0
 #define TZ_STATE_RESUME  1
@@ -387,6 +388,7 @@ static int __cam_lx7_power_resume(struct cam_hw_info *lx7_info)
 	return 0;
 }
 
+#ifndef CONFIG_CAM_PRESIL
 /* Used for non secure FW load */
 static int32_t __cam_non_sec_load_fw(void *device_priv)
 {
@@ -477,6 +479,19 @@ fw_download_failed:
 	release_firmware(core_info->fw_params.fw_elf);
 	return rc;
 }
+#else /* #ifndef CONFIG_CAM_PRESIL */
+static int __cam_non_sec_load_fw(struct cam_hw_info *lx7_info)
+{
+	if (!lx7_info) {
+		CAM_ERR(CAM_ICP, "invalid lx7 dev info");
+		return -EINVAL;
+	}
+
+	cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_ON_FIRST_REG_START_FW_DOWNLOAD, 0xFF);
+
+	return 0;
+}
+#endif /* #ifndef CONFIG_CAM_PRESIL */
 
 /* Used for non secure FW load */
 static int cam_lx7_non_sec_boot(

+ 24 - 0
drivers/cam_presil/inc/cam_presil_hw_access.h

@@ -8,6 +8,17 @@
 
 #include <linux/interrupt.h>
 
+/* presil events to carry shared values from HW-KMD to PC-HOST CSim Wrapper */
+#define CAM_PRESIL_EVENT_HFI_REG_BASE                             0x600
+#define CAM_PRESIL_EVENT_HFI_REG(n) (CAM_PRESIL_EVENT_HFI_REG_BASE + (n * 4))
+#define CAM_PRESIL_EVENT_HFI_REG_CMD_Q_IOVA                      CAM_PRESIL_EVENT_HFI_REG(1)
+#define CAM_PRESIL_EVENT_HFI_REG_MSG_Q_IOVA                      CAM_PRESIL_EVENT_HFI_REG(2)
+#define CAM_PRESIL_EVENT_HFI_REG_DBG_Q_IOVA                      CAM_PRESIL_EVENT_HFI_REG(3)
+#define CAM_PRESIL_EVENT_HFI_REG_SFR_LEN                         CAM_PRESIL_EVENT_HFI_REG(4)
+#define CAM_PRESIL_EVENT_HFI_REG_A5_HW_VERSION_TO_START_HFI_INIT CAM_PRESIL_EVENT_HFI_REG(13)
+#define CAM_PRESIL_EVENT_HFI_REG_ON_FIRST_REG_START_FW_DOWNLOAD    0x638   /* write FF to start */
+
+
 /*
  * enum cam_presil_err - return code from presil apis
  *
@@ -195,4 +206,17 @@ int cam_presil_hfi_read_message(uint32_t *pmsg, uint8_t q_id,
  * @return true or false.
  */
 bool cam_presil_mode_enabled(void);
+
+/*
+ *  cam_presil_send_event()
+ *
+ * @brief   :  send event to pchost.
+ *
+ * @event_id :  Event Id
+ * @value  :  Value with additional information
+ *
+ * @return:  Success or Failure
+ */
+int cam_presil_send_event(uint32_t event_id, uint32_t value);
+
 #endif /* _CAM_PRESIL_HW_ACCESS_H_ */

+ 6 - 0
drivers/cam_presil/stub/cam_presil_hw_access_stub.c

@@ -60,3 +60,9 @@ int cam_presil_hfi_read_message(uint32_t *pmsg, uint8_t q_id,
 {
 	return CAM_PRESIL_SUCCESS;
 }
+
+int cam_presil_send_event(uint32_t event_id, uint32_t value)
+{
+	return CAM_PRESIL_SUCCESS;
+}
+