diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 3768f06b17..5abba72b24 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -12,6 +12,7 @@ #include #include +#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 */ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 021c010824..9658df5743 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/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) diff --git a/drivers/cam_icp/icp_hw/lx7_hw/lx7_core.c b/drivers/cam_icp/icp_hw/lx7_hw/lx7_core.c index 24b9476652..b2a68f81ad 100644 --- a/drivers/cam_icp/icp_hw/lx7_hw/lx7_core.c +++ b/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( diff --git a/drivers/cam_presil/inc/cam_presil_hw_access.h b/drivers/cam_presil/inc/cam_presil_hw_access.h index 4b9421c7a6..72054ac941 100644 --- a/drivers/cam_presil/inc/cam_presil_hw_access.h +++ b/drivers/cam_presil/inc/cam_presil_hw_access.h @@ -8,6 +8,17 @@ #include +/* 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_ */ diff --git a/drivers/cam_presil/stub/cam_presil_hw_access_stub.c b/drivers/cam_presil/stub/cam_presil_hw_access_stub.c index 047a39b745..1b205e32a7 100644 --- a/drivers/cam_presil/stub/cam_presil_hw_access_stub.c +++ b/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; +} +