diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index 9d83f6b171..ebfb470804 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -12,6 +12,9 @@ #define HFI_CMD_Q_MINI_DUMP_SIZE_IN_BYTES 4096 #define HFI_MSG_Q_MINI_DUMP_SIZE_IN_BYTES 4096 +#define HFI_NUM_MAX 2 +#define HFI_HANDLE_INIT_VALUE HFI_NUM_MAX + /** * struct hfi_mem * @len: length of memory @@ -84,14 +87,16 @@ struct hfi_mini_dump_info { }; /** * hfi_write_cmd() - function for hfi write + * @client_handle: client handle * @cmd_ptr: pointer to command data for hfi write * * Returns success(zero)/failure(non zero) */ -int hfi_write_cmd(void *cmd_ptr); +int hfi_write_cmd(int client_handle, void *cmd_ptr); /** * hfi_read_message() - function for hfi read + * @client_handle: client handle * @pmsg: buffer to place read message for hfi queue * @q_id: queue id * @words_read: total number of words read from the queue @@ -99,10 +104,11 @@ int hfi_write_cmd(void *cmd_ptr); * * Returns success(zero)/failure(non zero) */ -int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); +int hfi_read_message(int client_handle, uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); /** * hfi_init() - function initialize hfi after firmware download + * @client_handle: client handle * @hfi_mem: hfi memory info * @hfi_ops: processor-specific hfi ops * @priv: device private data @@ -110,8 +116,24 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); * * Returns success(zero)/failure(non zero) */ -int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, - void *priv, uint8_t event_driven_mode); +int cam_hfi_init(int client_handle, struct hfi_mem_info *hfi_mem, + const struct hfi_ops *hfi_ops, void *priv, uint8_t event_driven_modem); + +/** + * cam_hfi_register() - function to register user as hfi client and retrieve handle + * @client_handle: client handle to be retrieved + * + * Returns success(zero)/failure(non zero) + */ +int cam_hfi_register(int *client_handle); + +/** + * cam_hfi_unregister() - function to unregister hfi client + * @client_handle: client handle + * + * Returns success(zero)/failure(non zero) + */ +int cam_hfi_unregister(int *client_handle); /** * hfi_get_hw_caps() - hardware capabilities from firmware @@ -123,79 +145,92 @@ int hfi_get_hw_caps(void *query_caps); /** * hfi_send_system_cmd() - send hfi system command to firmware + * @client_handle: client handle * @type: type of system command * @data: command data * @size: size of command data + * + * Returns success(zero)/failure(non zero) */ -void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size); +int hfi_send_system_cmd(int client_handle, uint32_t type, uint64_t data, uint32_t size); /** * cam_hfi_deinit() - cleanup HFI + * @client_handle: client handle to be retrieved */ -void cam_hfi_deinit(void); +void cam_hfi_deinit(int client_handle); /** * hfi_set_debug_level() - set debug level + * @client_handle: client handle to be retrieved * @icp_dbg_type: 1 for debug_q & 2 for qdss * @lvl: FW debug message level + * + * Returns success(zero)/failure(non zero) */ -int hfi_set_debug_level(u64 icp_dbg_type, uint32_t lvl); +int hfi_set_debug_level(int client_handle, u64 icp_dbg_type, uint32_t lvl); /** * hfi_set_fw_dump_levels() - set firmware hang dump/ramdump levels + * @client_handle: client handle to be retrieved * @hang_dump_lvl : level of firmware hang dump * @ram_dump_lvl : level of firmware ram dump + * + * Returns success(zero)/failure(non zero) */ -int hfi_set_fw_dump_levels(uint32_t hang_dump_lvl, uint32_t ram_dump_lvl); +int hfi_set_fw_dump_levels(int client_handle, + uint32_t hang_dump_lvl, uint32_t ram_dump_lvl); /** * hfi_send_freq_info() - set firmware dump level + * @client_handle: client handle to be retrieved * @freq: icp freq - */ -int hfi_send_freq_info(int32_t freq); - -/** - * hfi_enable_dev_pc() - Enable interframe pc - * Host sends a command to firmware to enable interframe - * power collapse for ICP's controlled hardware. * - * @enable: flag to enable/disable - * @core_info: Core information to firmware + * Returns success(zero)/failure(non zero) */ -int hfi_enable_dev_pc(bool enable, uint32_t core_info); +int hfi_send_freq_info(int client_handle, int32_t freq); /** * hfi_cmd_ubwc_config_ext() - UBWC configuration to firmware + * @client_handle: client handle to be retrieved * @ubwc_ipe_cfg: UBWC ipe fetch/write configuration params * @ubwc_bps_cfg: UBWC bps fetch/write configuration params + * @ubwc_ofe_cfg: UBWC ofe fetch/write configuration params + * + * Returns success(zero)/failure(non zero) */ -int hfi_cmd_ubwc_config_ext(uint32_t *ubwc_ipe_cfg, - uint32_t *ubwc_bps_cfg); +int hfi_cmd_ubwc_config_ext(int client_handle, uint32_t *ubwc_ipe_cfg, + uint32_t *ubwc_bps_cfg, uint32_t *ubwc_ofe_cfg); /** * hfi_cmd_ubwc_config() - UBWC configuration to firmware * for older targets + * @client_handle: client handle to be retrieved * @ubwc_cfg: UBWC configuration parameters - */ -int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg); - -/** - * cam_hfi_resume() - function to resume - * @hfi_mem: hfi memory info * * Returns success(zero)/failure(non zero) */ -int cam_hfi_resume(struct hfi_mem_info *hfi_mem); +int hfi_cmd_ubwc_config(int client_handle, uint32_t *ubwc_cfg); + +/** + * cam_hfi_resume() - function to resume + * @client_handle: client handle to be retrieved + * + * Returns success(zero)/failure(non zero) + */ +int cam_hfi_resume(int client_handle); /** * cam_hfi_queue_dump() - utility function to dump hfi queues + * @client_handle: client handle to be retrieved * @dump_queue_data: if set dumps queue contents - * */ -void cam_hfi_queue_dump(bool dump_queue_data); +void cam_hfi_queue_dump(int client_handle, bool dump_queue_data); /** * cam_hfi_mini_dump() - utility function for mini dump + * @client_handle: client handle to be retrieved + * @dst: memory destination */ -void cam_hfi_mini_dump(struct hfi_mini_dump_info *dst); +void cam_hfi_mini_dump(int client_handle, struct hfi_mini_dump_info *dst); #endif /* _HFI_INTF_H_ */ diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index 0d3ca7c444..8bede5c6ba 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -72,6 +72,10 @@ #define U32_OFFSET 0x1 #define BYTE_WORD_SHIFT 2 +#define HFI_GET_CLIENT_HANDLE(idx) (idx) +#define HFI_GET_INDEX(client_handle) (client_handle) +#define IS_VALID_HFI_INDEX(idx) (((idx) >= 0) && ((idx) < HFI_NUM_MAX)) + /** * @INVALID: Invalid state * @HFI_DEINIT: HFI is not initialized yet diff --git a/drivers/cam_icp/fw_inc/hfi_sys_defs.h b/drivers/cam_icp/fw_inc/hfi_sys_defs.h index aac65ede0f..2b63987c82 100644 --- a/drivers/cam_icp/fw_inc/hfi_sys_defs.h +++ b/drivers/cam_icp/fw_inc/hfi_sys_defs.h @@ -270,6 +270,11 @@ #define HFI_DEV_VERSION_MAX 0x6 +#define ICP_PWR_CLP_BPS 0x00000001 +#define ICP_PWR_CLP_IPE0 0x00010000 +#define ICP_PWR_CLP_IPE1 0x00020000 +#define ICP_PWR_CLP_OFE 0x00000001 + /** * start of sys command packet types * These commands are used to get system level information diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 198b027425..19df872264 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -27,7 +27,6 @@ #define HFI_VERSION_INFO_MAJOR_VAL 1 #define HFI_VERSION_INFO_MINOR_VAL 1 #define HFI_VERSION_INFO_STEP_VAL 0 -#define HFI_VERSION_INFO_STEP_VAL 0 #define HFI_VERSION_INFO_MAJOR_BMSK 0xFF000000 #define HFI_VERSION_INFO_MAJOR_SHFT 24 #define HFI_VERSION_INFO_MINOR_BMSK 0xFFFF00 @@ -39,11 +38,14 @@ #define HFI_POLL_DELAY_US 10 #define HFI_POLL_TIMEOUT_US 1500000 -static struct hfi_info *g_hfi; -unsigned int g_icp_mmu_hdl; +struct hfi_top_info { + uint32_t num_hfi; + struct hfi_info *hfi[HFI_NUM_MAX]; +}; + +struct hfi_top_info g_hfi; +static DEFINE_MUTEX(g_hfi_lock); -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); @@ -72,6 +74,27 @@ static void __iomem *hfi_iface_addr(struct hfi_info *hfi) return IS_ERR_OR_NULL(ret) ? NULL : ret; } +static inline int hfi_get_client_info(int client_handle, struct hfi_info **hfi) +{ + uint32_t idx; + + idx = HFI_GET_INDEX(client_handle); + if (!IS_VALID_HFI_INDEX(idx)) { + CAM_ERR(CAM_HFI, "Invalid HFI index: %u from hdl:%d", + idx, client_handle); + return -EINVAL; + } + + *hfi = g_hfi.hfi[idx]; + if (!g_hfi.hfi[idx]) { + CAM_ERR(CAM_HFI, "HFI interface not setup for client hdl: %d", + client_handle); + return -ENODEV; + } + + return 0; +} + static void hfi_queue_dump(uint32_t *dwords, int count) { int i; @@ -96,48 +119,68 @@ static void hfi_queue_dump(uint32_t *dwords, int count) rows * 4, dwords[0], dwords[1], dwords[2]); } -void cam_hfi_mini_dump(struct hfi_mini_dump_info *dst) +void cam_hfi_mini_dump(int client_handle, struct hfi_mini_dump_info *dst) { - struct hfi_mem_info *hfi_mem = &g_hfi->map; + struct hfi_info *hfi; + struct hfi_mem_info *hfi_mem; struct hfi_qtbl *qtbl; struct hfi_q_hdr *q_hdr; uint32_t *dwords; - int num_dwords; + int rc; + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d", + rc, client_handle); + return; + } + + hfi_mem = &hfi->map; if (!hfi_mem) { - CAM_ERR(CAM_HFI, "hfi mem info NULL... unable to dump queues"); + CAM_ERR(CAM_HFI, "hfi mem info NULL... unable to dump queues for hdl: %d", + client_handle); return; } qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva; q_hdr = &qtbl->q_hdr[Q_CMD]; dwords = (uint32_t *)hfi_mem->cmd_q.kva; - num_dwords = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; memcpy(dst->cmd_q, dwords, ICP_CMD_Q_SIZE_IN_BYTES); q_hdr = &qtbl->q_hdr[Q_MSG]; dwords = (uint32_t *)hfi_mem->msg_q.kva; memcpy(dst->msg_q, dwords, ICP_CMD_Q_SIZE_IN_BYTES); - dst->msg_q_state = g_hfi->msg_q_state; - dst->cmd_q_state = g_hfi->cmd_q_state; + dst->msg_q_state = hfi->msg_q_state; + dst->cmd_q_state = hfi->cmd_q_state; } -void cam_hfi_queue_dump(bool dump_queue_data) +void cam_hfi_queue_dump(int client_handle, bool dump_queue_data) { - struct hfi_mem_info *hfi_mem = &g_hfi->map; + struct hfi_info *hfi; + struct hfi_mem_info *hfi_mem; struct hfi_qtbl *qtbl; struct hfi_q_hdr *q_hdr; uint32_t *dwords; - int num_dwords; + int num_dwords, rc; + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d", + rc, client_handle); + return; + } + + hfi_mem = &hfi->map; if (!hfi_mem) { - CAM_ERR(CAM_HFI, "hfi mem info NULL... unable to dump queues"); + CAM_ERR(CAM_HFI, "mem info NULL... unable to dump queues for hdl: %d", + client_handle); return; } qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva; CAM_INFO(CAM_HFI, - "qtbl header: version=0x%08x tbl_size=%u numq=%u qhdr_size=%u", + "hfi hdl: %u qtbl header: version=0x%08x tbl_size=%u numq=%u qhdr_size=%u", + client_handle, qtbl->q_tbl_hdr.qtbl_version, qtbl->q_tbl_hdr.qtbl_size, qtbl->q_tbl_hdr.qtbl_num_q, @@ -173,42 +216,45 @@ void cam_hfi_queue_dump(bool dump_queue_data) } #ifndef CONFIG_CAM_PRESIL -int hfi_write_cmd(void *cmd_ptr) +int hfi_write_cmd(int client_handle, void *cmd_ptr) { uint32_t size_in_words, empty_space, new_write_idx, read_idx, temp; uint32_t *write_q, *write_ptr; + struct hfi_info *hfi; struct hfi_qtbl *q_tbl; struct hfi_q_hdr *q; int rc = 0; + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d", + rc, client_handle); + return rc; + } + if (!cmd_ptr) { - CAM_ERR(CAM_HFI, "command is null"); + CAM_ERR(CAM_HFI, "command is null for hfi hdl: %d", + client_handle); return -EINVAL; } - mutex_lock(&hfi_cmd_q_mutex); - if (!g_hfi) { - CAM_ERR(CAM_HFI, "HFI interface not setup"); + mutex_lock(&hfi->cmd_q_lock); + if (hfi->hfi_state != HFI_READY || + !hfi->cmd_q_state) { + CAM_ERR(CAM_HFI, "Invalid hfi state: %u cmd q state: %u hfi hdl: %d", + hfi->hfi_state, hfi->cmd_q_state, client_handle); rc = -ENODEV; goto err; } - if (g_hfi->hfi_state != HFI_READY || - !g_hfi->cmd_q_state) { - CAM_ERR(CAM_HFI, "HFI state: %u, cmd q state: %u", - g_hfi->hfi_state, g_hfi->cmd_q_state); - rc = -ENODEV; - goto err; - } - - q_tbl = (struct hfi_qtbl *)g_hfi->map.qtbl.kva; + q_tbl = (struct hfi_qtbl *)hfi->map.qtbl.kva; q = &q_tbl->q_hdr[Q_CMD]; - write_q = (uint32_t *)g_hfi->map.cmd_q.kva; + write_q = (uint32_t *)hfi->map.cmd_q.kva; size_in_words = (*(uint32_t *)cmd_ptr) >> BYTE_WORD_SHIFT; if (!size_in_words) { - CAM_DBG(CAM_HFI, "failed"); + CAM_DBG(CAM_HFI, "hfi hdl: %u word size is NULL"); rc = -EINVAL; goto err; } @@ -218,7 +264,7 @@ int hfi_write_cmd(void *cmd_ptr) (q->qhdr_q_size - (q->qhdr_write_idx - read_idx)) : (read_idx - q->qhdr_write_idx); if (empty_space <= size_in_words) { - CAM_ERR(CAM_HFI, "failed: empty space %u, size_in_words %u", + CAM_ERR(CAM_HFI, "hfi hdl: %u failed: empty space %u, size_in_words %u", empty_space, size_in_words); rc = -EIO; goto err; @@ -251,18 +297,19 @@ int hfi_write_cmd(void *cmd_ptr) * firmware to process */ wmb(); - hfi_irq_raise(g_hfi); + hfi_irq_raise(hfi); /* Ensure HOST2ICP trigger is received by FW */ wmb(); err: - mutex_unlock(&hfi_cmd_q_mutex); + mutex_unlock(&hfi->cmd_q_lock); return rc; } -int hfi_read_message(uint32_t *pmsg, uint8_t q_id, +int hfi_read_message(int client_handle, uint32_t *pmsg, uint8_t q_id, uint32_t *words_read) { + struct hfi_info *hfi; struct hfi_qtbl *q_tbl_ptr; struct hfi_q_hdr *q; uint32_t new_read_idx, size_in_words, word_diff, temp; @@ -270,8 +317,15 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t size_upper_bound = 0; int rc = 0; + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl:%d", + rc, client_handle); + return rc; + } + if (!pmsg) { - CAM_ERR(CAM_HFI, "Invalid msg"); + CAM_ERR(CAM_HFI, "client hdl: %d Invalid msg", client_handle); return -EINVAL; } @@ -280,36 +334,30 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, return -EINVAL; } - mutex_lock(&hfi_msg_q_mutex); - if (!g_hfi) { - CAM_ERR(CAM_HFI, "hfi not set up yet"); + mutex_lock(&hfi->msg_q_lock); + if (hfi->hfi_state != HFI_READY || + !hfi->msg_q_state) { + CAM_ERR(CAM_HFI, "Invalid hfi state:%u msg q state: %u hfi hdl: %d", + hfi->hfi_state, hfi->msg_q_state, client_handle); rc = -ENODEV; goto err; } - if ((g_hfi->hfi_state != HFI_READY) || - !g_hfi->msg_q_state) { - CAM_ERR(CAM_HFI, "hfi state: %u, msg q state: %u", - g_hfi->hfi_state, g_hfi->msg_q_state); - rc = -ENODEV; - goto err; - } - - q_tbl_ptr = (struct hfi_qtbl *)g_hfi->map.qtbl.kva; + q_tbl_ptr = (struct hfi_qtbl *)hfi->map.qtbl.kva; q = &q_tbl_ptr->q_hdr[q_id]; if (q->qhdr_read_idx == q->qhdr_write_idx) { - CAM_DBG(CAM_HFI, "Q not ready, state:%u, r idx:%u, w idx:%u", - g_hfi->hfi_state, q->qhdr_read_idx, q->qhdr_write_idx); + CAM_DBG(CAM_HFI, "hfi hdl: %d Q not ready, state:%u, r idx:%u, w idx:%u", + client_handle, hfi->hfi_state, q->qhdr_read_idx, q->qhdr_write_idx); rc = -EIO; goto err; } size_upper_bound = q->qhdr_q_size; if (q_id == Q_MSG) - read_q = (uint32_t *)g_hfi->map.msg_q.kva; + read_q = (uint32_t *)hfi->map.msg_q.kva; else - read_q = (uint32_t *)g_hfi->map.dbg_q.kva; + read_q = (uint32_t *)hfi->map.dbg_q.kva; read_ptr = (uint32_t *)(read_q + q->qhdr_read_idx); write_ptr = (uint32_t *)(read_q + q->qhdr_write_idx); @@ -323,8 +371,8 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, if ((size_in_words == 0) || (size_in_words > size_upper_bound)) { - CAM_ERR(CAM_HFI, "invalid HFI message packet size - 0x%08x", - size_in_words << BYTE_WORD_SHIFT); + CAM_ERR(CAM_HFI, "Invalid HFI message packet size - 0x%08x hfi hdl:%d", + size_in_words << BYTE_WORD_SHIFT, client_handle); q->qhdr_read_idx = q->qhdr_write_idx; rc = -EIO; goto err; @@ -349,12 +397,12 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, */ wmb(); err: - mutex_unlock(&hfi_msg_q_mutex); + mutex_unlock(&hfi->msg_q_lock); return rc; } #endif /* #ifndef CONFIG_CAM_PRESIL */ -int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg) +int hfi_cmd_ubwc_config(int client_handle, uint32_t *ubwc_cfg) { uint8_t *prop; struct hfi_cmd_prop *dbg_prop; @@ -364,8 +412,8 @@ int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg) sizeof(struct hfi_cmd_ubwc_cfg); CAM_DBG(CAM_HFI, - "size of ubwc %u, ubwc_cfg [rd-0x%x,wr-0x%x]", - size, ubwc_cfg[0], ubwc_cfg[1]); + "hfi hdl: %d size of ubwc %u, ubwc_cfg [rd-0x%x,wr-0x%x]", + client_handle, size, ubwc_cfg[0], ubwc_cfg[1]); prop = kzalloc(size, GFP_KERNEL); if (!prop) @@ -379,14 +427,14 @@ int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg) dbg_prop->prop_data[1] = ubwc_cfg[0]; dbg_prop->prop_data[2] = ubwc_cfg[1]; - hfi_write_cmd(prop); + hfi_write_cmd(client_handle, prop); kfree(prop); return 0; } -int hfi_cmd_ubwc_config_ext(uint32_t *ubwc_ipe_cfg, - uint32_t *ubwc_bps_cfg) +int hfi_cmd_ubwc_config_ext(int client_handle, uint32_t *ubwc_ipe_cfg, + uint32_t *ubwc_bps_cfg, uint32_t *ubwc_ofe_cfg) { uint8_t *prop; struct hfi_cmd_prop *dbg_prop; @@ -396,9 +444,9 @@ int hfi_cmd_ubwc_config_ext(uint32_t *ubwc_ipe_cfg, sizeof(struct hfi_cmd_ubwc_cfg_ext); CAM_DBG(CAM_HFI, - "size of ubwc %u, ubwc_ipe_cfg[rd-0x%x,wr-0x%x] ubwc_bps_cfg[rd-0x%x,wr-0x%x]", - size, ubwc_ipe_cfg[0], ubwc_ipe_cfg[1], - ubwc_bps_cfg[0], ubwc_bps_cfg[1]); + "hfi hdl: %d size of ubwc %u, ubwc_ipe_cfg[rd-0x%x,wr-0x%x] ubwc_bps_cfg[rd-0x%x,wr-0x%x] ubwc_ofe_cfg[rd-0x%x,wr-0x%x]", + client_handle, size, ubwc_ipe_cfg[0], ubwc_ipe_cfg[1], ubwc_bps_cfg[0], + ubwc_bps_cfg[1], ubwc_ofe_cfg[0], ubwc_ofe_cfg[1]); prop = kzalloc(size, GFP_KERNEL); if (!prop) @@ -413,46 +461,28 @@ int hfi_cmd_ubwc_config_ext(uint32_t *ubwc_ipe_cfg, dbg_prop->prop_data[2] = ubwc_bps_cfg[1]; dbg_prop->prop_data[3] = ubwc_ipe_cfg[0]; dbg_prop->prop_data[4] = ubwc_ipe_cfg[1]; - - hfi_write_cmd(prop); + dbg_prop->prop_data[5] = ubwc_ofe_cfg[0]; + dbg_prop->prop_data[6] = ubwc_ofe_cfg[1]; + hfi_write_cmd(client_handle, prop); kfree(prop); return 0; } - -int hfi_enable_dev_pc(bool enable, uint32_t core_info) -{ - uint8_t *prop; - struct hfi_cmd_prop *dbg_prop; - uint32_t size = 0; - - size = sizeof(struct hfi_cmd_prop) + - sizeof(struct hfi_dev_pc); - - prop = kzalloc(size, GFP_KERNEL); - if (!prop) - return -ENOMEM; - - dbg_prop = (struct hfi_cmd_prop *)prop; - dbg_prop->size = size; - dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY; - dbg_prop->num_prop = 1; - dbg_prop->prop_data[0] = HFI_PROP_SYS_IPEBPS_PC; - dbg_prop->prop_data[1] = enable; - dbg_prop->prop_data[2] = core_info; - - hfi_write_cmd(prop); - kfree(prop); - - return 0; -} - -int hfi_set_debug_level(u64 icp_dbg_type, uint32_t lvl) +int hfi_set_debug_level(int client_handle, u64 icp_dbg_type, uint32_t lvl) { uint8_t *prop; + struct hfi_info *hfi; struct hfi_cmd_prop *dbg_prop; uint32_t size = 0, val; + int rc; + + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d", + rc, client_handle); + return rc; + } val = HFI_DEBUG_MSG_LOW | HFI_DEBUG_MSG_MEDIUM | @@ -466,8 +496,8 @@ int hfi_set_debug_level(u64 icp_dbg_type, uint32_t lvl) if (lvl > val) return -EINVAL; - if (g_hfi) - g_hfi->dbg_lvl = lvl; + if (hfi) + hfi->dbg_lvl = lvl; size = sizeof(struct hfi_cmd_prop) + sizeof(struct hfi_debug); @@ -483,21 +513,31 @@ int hfi_set_debug_level(u64 icp_dbg_type, uint32_t lvl) dbg_prop->prop_data[0] = HFI_PROP_SYS_DEBUG_CFG; dbg_prop->prop_data[1] = lvl; dbg_prop->prop_data[2] = icp_dbg_type; - hfi_write_cmd(prop); + hfi_write_cmd(client_handle, prop); kfree(prop); return 0; } -int hfi_set_fw_dump_levels(uint32_t hang_dump_lvl, +int hfi_set_fw_dump_levels(int client_handle, uint32_t hang_dump_lvl, uint32_t ram_dump_lvl) { uint8_t *prop = NULL; + struct hfi_info *hfi; struct hfi_cmd_prop *fw_dump_level_switch_prop = NULL; uint32_t size = 0; + int rc; - CAM_DBG(CAM_HFI, "fw dump ENTER"); + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d", + rc, client_handle); + return rc; + } + + CAM_DBG(CAM_HFI, "hfi hdl: %d fw dump ENTER", + client_handle); size = sizeof(struct hfi_cmd_prop) + sizeof(uint32_t); prop = kzalloc(size, GFP_KERNEL); @@ -512,15 +552,16 @@ int hfi_set_fw_dump_levels(uint32_t hang_dump_lvl, fw_dump_level_switch_prop->prop_data[1] = hang_dump_lvl; /* Write hang dump level */ - hfi_write_cmd(prop); + hfi_write_cmd(client_handle, prop); /* Update and write ramdump level */ fw_dump_level_switch_prop->prop_data[0] = HFI_PROP_SYS_ICP_RAMDUMP_MODE; fw_dump_level_switch_prop->prop_data[1] = ram_dump_lvl; - hfi_write_cmd(prop); + hfi_write_cmd(client_handle, prop); CAM_DBG(CAM_HFI, - "prop->size = %d prop->pkt_type = %d prop->num_prop = %d hang_dump_lvl = %u ram_dump_lvl = %u", + "hfi hdl: %d prop->size = %d prop->pkt_type = %d prop->num_prop = %d hang_dump_lvl = %u ram_dump_lvl = %u", + client_handle, fw_dump_level_switch_prop->size, fw_dump_level_switch_prop->pkt_type, fw_dump_level_switch_prop->num_prop, @@ -530,18 +571,22 @@ int hfi_set_fw_dump_levels(uint32_t hang_dump_lvl, return 0; } -int hfi_send_freq_info(int32_t freq) +int hfi_send_freq_info(int client_handle, int32_t freq) { uint8_t *prop = NULL; + struct hfi_info *hfi; struct hfi_cmd_prop *dbg_prop = NULL; uint32_t size = 0; + int rc; - if (!g_hfi) { - CAM_ERR(CAM_HFI, "HFI interface not setup"); - return -ENODEV; + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d", + rc, client_handle); + return rc; } - if (!(g_hfi->dbg_lvl & HFI_DEBUG_MSG_PERF)) + if (!(hfi->dbg_lvl & HFI_DEBUG_MSG_PERF)) return -EINVAL; size = sizeof(struct hfi_cmd_prop) + sizeof(freq); @@ -556,33 +601,43 @@ int hfi_send_freq_info(int32_t freq) dbg_prop->prop_data[0] = HFI_PROP_SYS_ICP_HW_FREQUENCY; dbg_prop->prop_data[1] = freq; - CAM_DBG(CAM_HFI, "prop->size = %d\n" + CAM_DBG(CAM_HFI, + "hfi hdl: %d\n" + "prop->size = %d\n" "prop->pkt_type = %d\n" "prop->num_prop = %d\n" "prop->prop_data[0] = %d\n" "prop->prop_data[1] = %d\n" "dbg_lvl = 0x%x\n", + client_handle, dbg_prop->size, dbg_prop->pkt_type, dbg_prop->num_prop, dbg_prop->prop_data[0], dbg_prop->prop_data[1], - g_hfi->dbg_lvl); + hfi->dbg_lvl); - hfi_write_cmd(prop); + hfi_write_cmd(client_handle, prop); kfree(prop); return 0; } -void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size) +int hfi_send_system_cmd(int client_handle, uint32_t type, uint64_t data, uint32_t size) { + int rc = 0; + + if (!IS_VALID_HFI_INDEX(client_handle)) { + CAM_ERR(CAM_HFI, "Invalid client handle: %d", client_handle); + return -EINVAL; + } + switch (type) { case HFI_CMD_SYS_INIT: { struct hfi_cmd_sys_init init; init.size = sizeof(struct hfi_cmd_sys_init); init.pkt_type = type; - hfi_write_cmd(&init); + rc = hfi_write_cmd(client_handle, &init); } break; case HFI_CMD_SYS_PC_PREP: { @@ -590,7 +645,7 @@ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size) prep.size = sizeof(struct hfi_cmd_pc_prep); prep.pkt_type = type; - hfi_write_cmd(&prep); + rc = hfi_write_cmd(client_handle, &prep); } break; case HFI_CMD_SYS_SET_PROPERTY: { @@ -601,7 +656,7 @@ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size) prop.pkt_type = type; prop.num_prop = 1; prop.prop_data[0] = HFI_PROP_SYS_DEBUG_CFG; - hfi_write_cmd(&prop); + rc = hfi_write_cmd(client_handle, &prop); } } break; @@ -613,7 +668,7 @@ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size) ping.size = sizeof(struct hfi_cmd_ping_pkt); ping.pkt_type = type; ping.user_data = (uint64_t)data; - hfi_write_cmd(&ping); + rc = hfi_write_cmd(client_handle, &ping); } break; case HFI_CMD_SYS_RESET: { @@ -622,7 +677,7 @@ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size) reset.size = sizeof(struct hfi_cmd_sys_reset_pkt); reset.pkt_type = type; reset.user_data = (uint64_t)data; - hfi_write_cmd(&reset); + rc = hfi_write_cmd(client_handle, &reset); } break; case HFI_CMD_IPEBPS_CREATE_HANDLE: { @@ -632,15 +687,18 @@ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size) handle.pkt_type = type; handle.handle_type = (uint32_t)data; handle.user_data1 = 0; - hfi_write_cmd(&handle); + rc = hfi_write_cmd(client_handle, &handle); } break; case HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT: break; default: - CAM_ERR(CAM_HFI, "command not supported :%d", type); + CAM_ERR(CAM_HFI, "command not supported: %u client handle: %d", + type, client_handle); break; } + + return rc; } @@ -675,31 +733,44 @@ int hfi_get_hw_caps(void *query_buf) return 0; } -int cam_hfi_resume(struct hfi_mem_info *hfi_mem) +int cam_hfi_resume(int client_handle) { int rc = 0; + struct hfi_info *hfi; + struct hfi_mem_info *hfi_mem; uint32_t fw_version, status = 0; - void __iomem *icp_base = hfi_iface_addr(g_hfi); + void __iomem *icp_base = NULL; + + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl:%d", + rc, client_handle); + return rc; + } + + icp_base = hfi_iface_addr(hfi); if (!icp_base) { - CAM_ERR(CAM_HFI, "invalid HFI interface address"); + CAM_ERR(CAM_HFI, "invalid HFI interface address for hdl:%d", + client_handle); return -EINVAL; } if (cam_common_read_poll_timeout(icp_base + - HFI_REG_ICP_HOST_INIT_RESPONSE, - HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US, - (uint32_t)UINT_MAX, ICP_INIT_RESP_SUCCESS, &status)) { - CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x", - status); - return -ETIMEDOUT; + HFI_REG_ICP_HOST_INIT_RESPONSE, + HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US, + (uint32_t)UINT_MAX, ICP_INIT_RESP_SUCCESS, &status)) { + CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x hfi hdl: %d", + status, client_handle); + return -ETIMEDOUT; } - hfi_irq_enable(g_hfi); + hfi_irq_enable(hfi); fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); - CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version); + CAM_DBG(CAM_HFI, "hfi hdl: %d fw version : [%x]", client_handle, fw_version); + hfi_mem = &hfi->map; cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR); cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova, icp_base + HFI_REG_SFR_PTR); @@ -763,43 +834,38 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem) return rc; } -int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, - void *priv, uint8_t event_driven_mode) +int cam_hfi_init(int client_handle, struct hfi_mem_info *hfi_mem, + const struct hfi_ops *hfi_ops, + void *priv, uint8_t event_driven_mode) { int rc = 0; uint32_t status = 0; + struct hfi_info *hfi = NULL; struct hfi_qtbl *qtbl; struct hfi_qtbl_hdr *qtbl_hdr; struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; struct sfr_buf *sfr_buffer; void __iomem *icp_base; + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl %d", + rc, client_handle); + return rc; + } + if (!hfi_mem || !hfi_ops || !priv) { CAM_ERR(CAM_HFI, - "invalid arg: hfi_mem=%pK hfi_ops=%pK priv=%pK", - hfi_mem, hfi_ops, priv); + "invalid arg: hfi_mem=%pK hfi_ops=%pK priv=%pK hfi hdl:%d", + hfi_mem, hfi_ops, priv, client_handle); return -EINVAL; } - mutex_lock(&hfi_cmd_q_mutex); - mutex_lock(&hfi_msg_q_mutex); + mutex_lock(&hfi->cmd_q_lock); + mutex_lock(&hfi->msg_q_lock); - if (!g_hfi) { - g_hfi = kzalloc(sizeof(struct hfi_info), GFP_KERNEL); - if (!g_hfi) { - rc = -ENOMEM; - goto alloc_fail; - } - } - - if (g_hfi->hfi_state != HFI_DEINIT) { - CAM_ERR(CAM_HFI, "hfi_init: invalid state"); - rc = -EINVAL; - goto regions_fail; - } - - memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map)); - g_hfi->hfi_state = HFI_DEINIT; + hfi->hfi_state = HFI_INIT; + memcpy(&hfi->map, hfi_mem, sizeof(hfi->map)); qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva; qtbl_hdr = &qtbl->q_tbl_hdr; @@ -910,17 +976,18 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, break; default: - CAM_ERR(CAM_HFI, "Invalid event driven mode :%u", - event_driven_mode); + CAM_ERR(CAM_HFI, "Invalid event driven mode :%u for hdl:%d", + event_driven_mode, client_handle); break; } - g_hfi->ops = *hfi_ops; - g_hfi->priv = priv; + hfi->ops = *hfi_ops; + hfi->priv = priv; - icp_base = hfi_iface_addr(g_hfi); + icp_base = hfi_iface_addr(hfi); if (!icp_base) { - CAM_ERR(CAM_HFI, "invalid HFI interface address"); + CAM_ERR(CAM_HFI, "invalid HFI interface address for hdl: %d", + client_handle); rc = -EINVAL; goto regions_fail; } @@ -962,6 +1029,8 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, cam_io_w_mb((uint32_t)hfi_mem->hwmutex.len, icp_base + HFI_REG_DEVICE_HWMUTEX_SIZE); + CAM_DBG(CAM_HFI, "HFI handle: %d", client_handle); + CAM_DBG(CAM_HFI, "IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]", hfi_mem->io_mem.iova, hfi_mem->io_mem.len, hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); @@ -992,9 +1061,9 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, 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, - (uint32_t)UINT_MAX, ICP_INIT_RESP_SUCCESS, &status)) { + HFI_REG_ICP_HOST_INIT_RESPONSE, + HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US, + (uint32_t)UINT_MAX, ICP_INIT_RESP_SUCCESS, &status)) { CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x", status); rc = -ETIMEDOUT; @@ -1004,49 +1073,162 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, CAM_DBG(CAM_HFI, "ICP fw version: 0x%x", cam_io_r(icp_base + HFI_REG_FW_VERSION)); - g_hfi->hfi_state = HFI_READY; - g_hfi->cmd_q_state = true; - g_hfi->msg_q_state = true; + hfi->cmd_q_state = true; + hfi->msg_q_state = true; + hfi->hfi_state = HFI_READY; - hfi_irq_enable(g_hfi); + hfi_irq_enable(hfi); - mutex_unlock(&hfi_cmd_q_mutex); - mutex_unlock(&hfi_msg_q_mutex); + mutex_unlock(&hfi->cmd_q_lock); + mutex_unlock(&hfi->msg_q_lock); return rc; + regions_fail: - kfree(g_hfi); - g_hfi = NULL; -alloc_fail: - mutex_unlock(&hfi_cmd_q_mutex); - mutex_unlock(&hfi_msg_q_mutex); + mutex_unlock(&hfi->cmd_q_lock); + mutex_unlock(&hfi->msg_q_lock); return rc; } -void cam_hfi_deinit(void) +void cam_hfi_deinit(int client_handle) { + struct hfi_info *hfi; + int rc; + + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d", + rc, client_handle); + return; + } + 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); + CAM_DBG(CAM_HFI, + "HFI hdl: %d SYS_RESET Needed in presil for back to back hfi_init success", + client_handle); + hfi_send_system_cmd(client_handle, HFI_CMD_SYS_RESET, 0, 0); } - mutex_lock(&hfi_cmd_q_mutex); - mutex_lock(&hfi_msg_q_mutex); + mutex_lock(&hfi->cmd_q_lock); + mutex_lock(&hfi->msg_q_lock); - if (!g_hfi) { - CAM_ERR(CAM_HFI, "hfi path not established yet"); - goto err; + hfi->hfi_state = HFI_DEINIT; + hfi->cmd_q_state = false; + hfi->msg_q_state = false; + + mutex_unlock(&hfi->cmd_q_lock); + mutex_unlock(&hfi->msg_q_lock); + + memset(&hfi->map, 0, sizeof(struct hfi_mem_info)); + memset(&hfi->ops, 0, sizeof(struct hfi_ops)); + hfi->smem_size = 0; + hfi->uncachedheap_size = 0; + memset(hfi->msgpacket_buf, 0, sizeof(ICP_HFI_MAX_MSG_SIZE_IN_WORDS)); + hfi->priv = NULL; + hfi->dbg_lvl = 0; +} + +static int hfi_get_free_index(uint32_t *free_index) +{ + int i; + + for (i = 0; i < HFI_NUM_MAX; i++) { + if (!g_hfi.hfi[i]) { + *free_index = i; + return 0; + } } - g_hfi->cmd_q_state = false; - g_hfi->msg_q_state = false; + return -EUSERS; +} - cam_free_clear((void *)g_hfi); - g_hfi = NULL; +int cam_hfi_register(int *client_handle) +{ + struct hfi_info *hfi = NULL; + uint32_t hfi_index; + int rc = 0; -err: - mutex_unlock(&hfi_cmd_q_mutex); - mutex_unlock(&hfi_msg_q_mutex); + if (!client_handle) { + CAM_ERR(CAM_HFI, "Client handle is NULL"); + return -EINVAL; + } + + mutex_lock(&g_hfi_lock); + if (IS_VALID_HFI_INDEX(*client_handle)) { + rc = hfi_get_client_info(*client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Unable to retrieve existing hfi info for handle:%d", + *client_handle); + rc = -EINVAL; + goto failed_hfi_register; + } + CAM_ERR(CAM_HFI, "HFI client handle:%d is already established", + *client_handle); + rc = -EINVAL; + goto failed_hfi_register; + } + + rc = hfi_get_free_index(&hfi_index); + if (rc) { + CAM_ERR(CAM_HFI, "No available hfi slots rc:%d", rc); + goto failed_hfi_register; + } + + hfi = kzalloc(sizeof(struct hfi_info), GFP_KERNEL); + if (!hfi) { + rc = -ENOMEM; + goto failed_hfi_register; + } + + if (hfi->hfi_state != HFI_DEINIT) { + CAM_ERR(CAM_HFI, "hfi_init: invalid state: %u hfi idx: %u", + hfi->hfi_state, hfi_index); + rc = -EINVAL; + goto hfi_failed_state; + } + + g_hfi.hfi[hfi_index] = hfi; + g_hfi.num_hfi++; + *client_handle = HFI_GET_CLIENT_HANDLE(hfi_index); + mutex_unlock(&g_hfi_lock); + + mutex_init(&hfi->cmd_q_lock); + mutex_init(&hfi->msg_q_lock); + + return rc; + +hfi_failed_state: + kfree(hfi); +failed_hfi_register: + mutex_unlock(&g_hfi_lock); + return rc; +} + +int cam_hfi_unregister(int *client_handle) +{ + struct hfi_info *hfi; + uint32_t idx; + int rc; + + rc = hfi_get_client_info(*client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d", + rc, client_handle); + return rc; + } + + mutex_lock(&g_hfi_lock); + mutex_destroy(&hfi->msg_q_lock); + mutex_destroy(&hfi->cmd_q_lock); + cam_free_clear((void *)hfi); + idx = HFI_GET_INDEX(*client_handle); + g_hfi.hfi[idx] = NULL; + g_hfi.num_hfi--; + mutex_unlock(&g_hfi_lock); + + *client_handle = HFI_HANDLE_INIT_VALUE; + + return 0; } @@ -1079,48 +1261,67 @@ static int cam_hfi_presil_set_init_request(void) return 0; } -int hfi_write_cmd(void *cmd_ptr) +int hfi_write_cmd(int client_handle, void *cmd_ptr) { + struct hfi_info *hfi; int presil_rc = CAM_PRESIL_BLOCKED; int rc = 0; + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl:%d", + rc, client_handle); + return rc; + } + if (!cmd_ptr) { - CAM_ERR(CAM_HFI, "command is null"); + CAM_ERR(CAM_HFI, "command is null for hfi hdl:%d", client_handle); return -EINVAL; } - mutex_lock(&hfi_cmd_q_mutex); + mutex_lock(&hfi->cmd_q_lock); presil_rc = cam_presil_hfi_write_cmd(cmd_ptr, (*(uint32_t *)cmd_ptr), CAM_PRESIL_CLIENT_ID_CAMERA); if ((presil_rc != CAM_PRESIL_SUCCESS) && (presil_rc != CAM_PRESIL_BLOCKED)) { - CAM_ERR(CAM_HFI, "failed presil rc %d", presil_rc); + CAM_ERR(CAM_HFI, "hfi hdl: %d failed presil rc %d", + client_handle, presil_rc); rc = -EINVAL; } else { - CAM_DBG(CAM_HFI, "presil rc %d", presil_rc); + CAM_DBG(CAM_HFI, "hfi hdl: %d presil rc %d", + client_handle, presil_rc); } - mutex_unlock(&hfi_cmd_q_mutex); + mutex_unlock(&hfi->cmd_q_lock); return rc; } -int hfi_read_message(uint32_t *pmsg, uint8_t q_id, +int hfi_read_message(int client_handle, uint32_t *pmsg, uint8_t q_id, uint32_t *words_read) { + struct hfi_info *hfi; int presil_rc = CAM_PRESIL_BLOCKED; int rc = 0; + rc = hfi_get_client_info(client_handle, &hfi); + if (rc) { + CAM_ERR(CAM_HFI, "Failed to get hfi info rc: %d for hdl: %d", + rc, client_handle); + return rc; + } + if (!pmsg) { - CAM_ERR(CAM_HFI, "Invalid msg"); + CAM_ERR(CAM_HFI, "Invalid msg for hdl: %d", client_handle); return -EINVAL; } if (q_id > Q_DBG) { - CAM_ERR(CAM_HFI, "Invalid q :%u", q_id); + CAM_ERR(CAM_HFI, "Invalid q :%u hdl: %d", + q_id, client_handle); return -EINVAL; } - mutex_lock(&hfi_msg_q_mutex); + mutex_lock(&hfi->msg_q_lock); memset(pmsg, 0x0, sizeof(uint32_t) * 256 /* ICP_MSG_BUF_SIZE */); *words_read = 0; @@ -1129,13 +1330,13 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, CAM_PRESIL_CLIENT_ID_CAMERA); if ((presil_rc != CAM_PRESIL_SUCCESS) && (presil_rc != CAM_PRESIL_BLOCKED)) { - CAM_ERR(CAM_HFI, "failed presil rc %d", presil_rc); + CAM_ERR(CAM_HFI, "hfi hdl: %d failed presil rc %d", client_handle, presil_rc); rc = -EINVAL; } else { - CAM_DBG(CAM_HFI, "presil rc %d", presil_rc); + CAM_DBG(CAM_HFI, "hfi hdl: %d presil rc %d", client_handle, presil_rc); } - mutex_unlock(&hfi_msg_q_mutex); + mutex_unlock(&hfi->msg_q_lock); return rc; } #else diff --git a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c index b6509908ac..e7bbda9803 100644 --- a/drivers/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/cam_icp/icp_hw/bps_hw/bps_core.c @@ -422,7 +422,7 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_bps_handle_resume(bps_dev); break; case CAM_ICP_DEV_CMD_UPDATE_CLK: { - struct cam_icp_clk_update_cmd *clk_upd_cmd = cmd_args; + struct cam_icp_dev_clk_update_cmd *clk_upd_cmd = cmd_args; struct cam_ahb_vote ahb_vote; uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; int32_t clk_level = 0, err = 0; 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 177c88be9b..38110f0ed6 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 @@ -155,7 +155,7 @@ static inline void cam_icp_dump_debug_info(struct cam_icp_hw_mgr *hw_mgr, dump_type = CAM_ICP_DUMP_STATUS_REGISTERS; cam_icp_mgr_process_dbg_buf(hw_mgr); - cam_hfi_queue_dump(false); + cam_hfi_queue_dump(hw_mgr->hfi_handle, false); rc = icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, CAM_ICP_CMD_HW_REG_DUMP, &dump_type, sizeof(dump_type)); @@ -166,18 +166,19 @@ static inline void cam_icp_dump_debug_info(struct cam_icp_hw_mgr *hw_mgr, static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr) { struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; + struct cam_icp_ubwc_cfg_cmd ubwc_cmd; int rc; - uint32_t disable_ubwc_comp = 0; if (!icp_dev_intf) { CAM_ERR(CAM_ICP, "ICP device interface is NULL"); return -EINVAL; } - disable_ubwc_comp = hw_mgr->disable_ubwc_comp; + ubwc_cmd.ubwc_cfg_dev_mask = hw_mgr->hw_cap_mask; + ubwc_cmd.disable_ubwc_comp = hw_mgr->disable_ubwc_comp; rc = icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, CAM_ICP_CMD_UBWC_CFG, - &disable_ubwc_comp, sizeof(disable_ubwc_comp)); + &ubwc_cmd, sizeof(ubwc_cmd)); if (rc) CAM_ERR(CAM_ICP, "Fail to submit UBWC config"); @@ -397,7 +398,7 @@ static int32_t cam_icp_deinit_idle_clk(void *priv, void *data) (struct cam_icp_clk_info *)task_data->data; struct cam_icp_hw_ctx_data *ctx_data; struct cam_hw_intf *dev_intf = NULL; - struct cam_icp_clk_update_cmd clk_upd_cmd; + struct cam_icp_dev_clk_update_cmd clk_upd_cmd; int rc = 0; uint32_t i, hw_dev_type; bool busy = false; @@ -1486,7 +1487,7 @@ static int cam_icp_update_clk_rate(struct cam_icp_hw_mgr *hw_mgr, uint32_t i, curr_clk_rate; struct cam_hw_intf *dev_intf = NULL; struct cam_icp_clk_info *hw_mgr_clk_info = NULL; - struct cam_icp_clk_update_cmd clk_upd_cmd; + struct cam_icp_dev_clk_update_cmd clk_upd_cmd; char tmp_buff[64]; hw_mgr_clk_info = &hw_mgr->clk_info[ctx_data->hw_clk_type]; @@ -1681,7 +1682,8 @@ static int cam_icp_mgr_device_resume(struct cam_icp_hw_mgr *hw_mgr, struct cam_icp_hw_ctx_data *ctx_data) { struct cam_hw_intf *dev_intf = NULL; - uint32_t core_info_mask = 0, num_dev, hw_dev_type, dev_info_idx; + struct hfi_cmd_prop *dbg_prop = NULL; + uint32_t core_info_mask = 0, num_dev, hw_dev_type, dev_info_idx, size; int rc = 0, i; hw_dev_type = ctx_data->hw_dev_type; @@ -1717,11 +1719,40 @@ static int cam_icp_mgr_device_resume(struct cam_icp_hw_mgr *hw_mgr, cam_icp_hw_dev_type_to_name(ctx_data->hw_dev_type), ctx_data->ctx_id, rc); } - CAM_DBG(CAM_PERF, "core_info %X", core_info_mask); - if (hw_mgr->dev_pc_flag) - rc = hfi_enable_dev_pc(true, core_info_mask); - else - rc = hfi_enable_dev_pc(false, core_info_mask); + CAM_DBG(CAM_PERF, "core_info 0x%x", core_info_mask); + + size = sizeof(struct hfi_cmd_prop) + sizeof(struct hfi_dev_pc); + dbg_prop = kzalloc(size, GFP_KERNEL); + if (!dbg_prop) { + CAM_ERR(CAM_ICP, "Allocate command prop failed"); + return -ENOMEM; + } + + dbg_prop->size = size; + dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY; + dbg_prop->num_prop = 1; + + switch (ctx_data->hw_dev_type) { + case CAM_ICP_DEV_IPE: + fallthrough; + case CAM_ICP_DEV_BPS: + dbg_prop->prop_data[0] = HFI_PROP_SYS_IPEBPS_PC; + break; + case CAM_ICP_DEV_OFE: + dbg_prop->prop_data[0] = HFI_PROP_SYS_OFE_PC; + break; + default: + CAM_ERR(CAM_ICP, "Invalid hw dev type: %u", + ctx_data->hw_dev_type); + return -EINVAL; + } + + dbg_prop->prop_data[1] = hw_mgr->dev_pc_flag; + dbg_prop->prop_data[2] = core_info_mask; + + hfi_write_cmd(hw_mgr->hfi_handle, dbg_prop); + + kfree(dbg_prop); end: return rc; @@ -2067,7 +2098,7 @@ static int cam_icp_mgr_process_cmd(void *priv, void *data) hw_mgr = priv; task_data = (struct hfi_cmd_work_data *)data; - rc = hfi_write_cmd(task_data->data); + rc = hfi_write_cmd(hw_mgr->hfi_handle, task_data->data); return rc; } @@ -2917,7 +2948,7 @@ static void cam_icp_mgr_process_dbg_buf(struct cam_icp_hw_mgr *hw_mgr) char *dbg_buf; int rc = 0; - rc = hfi_read_message(hw_mgr->dbg_buf, Q_DBG, &read_len); + rc = hfi_read_message(hw_mgr->hfi_handle, hw_mgr->dbg_buf, Q_DBG, &read_len); if (rc) return; @@ -3040,7 +3071,7 @@ static int32_t cam_icp_mgr_process_msg(void *priv, void *data) task_data = data; hw_mgr = priv; - rc = hfi_read_message(hw_mgr->msg_buf, Q_MSG, &read_len); + rc = hfi_read_message(hw_mgr->hfi_handle, hw_mgr->msg_buf, Q_MSG, &read_len); if (rc) { CAM_DBG(CAM_ICP, "Unable to read msg q rc %d", rc); } else { @@ -3807,7 +3838,7 @@ static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) if (rc) CAM_ERR(CAM_ICP, "Fail to power collapse ICP rc: %d", rc); - rc = icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, (void *)&send_freq_info, + rc = icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, &send_freq_info, sizeof(send_freq_info)); if (rc) CAM_ERR(CAM_ICP, "Fail to deinit ICP"); @@ -3857,18 +3888,21 @@ static int cam_icp_mgr_proc_boot(struct cam_icp_hw_mgr *hw_mgr) static void cam_icp_mgr_proc_shutdown(struct cam_icp_hw_mgr *hw_mgr) { struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; + bool send_freq_info = false; if (!icp_dev_intf) { CAM_ERR(CAM_ICP, "ICP device interface is NULL"); return; } - icp_dev_intf->hw_ops.init(icp_dev_intf->hw_priv, NULL, 0); + icp_dev_intf->hw_ops.init(icp_dev_intf->hw_priv, + &send_freq_info, sizeof(send_freq_info)); icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, CAM_ICP_CMD_PROC_SHUTDOWN, NULL, 0); - icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, NULL, 0); + icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, + &send_freq_info, sizeof(send_freq_info)); hw_mgr->icp_resumed = false; } @@ -3968,11 +4002,7 @@ static void cam_icp_mgr_populate_hfi_mem_info(struct cam_icp_hw_mgr *hw_mgr, static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) { - struct hfi_mem_info hfi_mem; - - cam_icp_mgr_populate_hfi_mem_info(hw_mgr, &hfi_mem); - - return cam_hfi_resume(&hfi_mem); + return cam_hfi_resume(hw_mgr->hfi_handle); } static int cam_icp_mgr_populate_abort_cmd(struct cam_icp_hw_ctx_data *ctx_data, @@ -4022,6 +4052,7 @@ static int cam_icp_mgr_populate_abort_cmd(struct cam_icp_hw_ctx_data *ctx_data, abort_cmd->user_data2 = (uint64_t)0x0; *abort_cmd_ptr = abort_cmd; + return 0; } @@ -4029,6 +4060,7 @@ static int cam_icp_mgr_abort_handle_wq( void *priv, void *data) { int rc = 0; + struct cam_icp_hw_mgr *hw_mgr; struct hfi_cmd_work_data *task_data = NULL; struct cam_icp_hw_ctx_data *ctx_data; struct hfi_cmd_dev_async *abort_cmd; @@ -4041,12 +4073,13 @@ static int cam_icp_mgr_abort_handle_wq( task_data = (struct hfi_cmd_work_data *)data; ctx_data = (struct cam_icp_hw_ctx_data *)task_data->data; + hw_mgr = ctx_data->hw_mgr_priv; rc = cam_icp_mgr_populate_abort_cmd(ctx_data, &abort_cmd); if (rc) return rc; - rc = hfi_write_cmd(abort_cmd); + rc = hfi_write_cmd(hw_mgr->hfi_handle, abort_cmd); if (rc) { kfree(abort_cmd); return rc; @@ -4064,6 +4097,7 @@ static int cam_icp_mgr_abort_handle(struct cam_icp_hw_ctx_data *ctx_data) unsigned long rem_jiffies = 0; int timeout = 2000; struct hfi_cmd_dev_async *abort_cmd; + struct cam_icp_hw_mgr *hw_mgr = ctx_data->hw_mgr_priv; rc = cam_icp_mgr_populate_abort_cmd(ctx_data, &abort_cmd); if (rc) @@ -4071,7 +4105,7 @@ static int cam_icp_mgr_abort_handle(struct cam_icp_hw_ctx_data *ctx_data) reinit_completion(&ctx_data->wait_complete); - rc = hfi_write_cmd(abort_cmd); + rc = hfi_write_cmd(hw_mgr->hfi_handle, abort_cmd); if (rc) { kfree(abort_cmd); return rc; @@ -4101,6 +4135,7 @@ static int cam_icp_mgr_destroy_handle( unsigned long rem_jiffies; size_t packet_size; struct hfi_cmd_dev_async *destroy_cmd; + struct cam_icp_hw_mgr *hw_mgr = ctx_data->hw_mgr_priv; packet_size = sizeof(struct hfi_cmd_dev_async); @@ -4146,7 +4181,7 @@ static int cam_icp_mgr_destroy_handle( reinit_completion(&ctx_data->wait_complete); - rc = hfi_write_cmd(destroy_cmd); + rc = hfi_write_cmd(hw_mgr->hfi_handle, destroy_cmd); if (rc) { kfree(destroy_cmd); return rc; @@ -4160,7 +4195,7 @@ static int cam_icp_mgr_destroy_handle( ctx_data->ctx_id_string); if (!rem_jiffies) { rc = -ETIMEDOUT; - cam_icp_dump_debug_info(ctx_data->hw_mgr_priv, ctx_data->abort_timed_out); + cam_icp_dump_debug_info(hw_mgr, ctx_data->abort_timed_out); } kfree(destroy_cmd); return rc; @@ -4256,7 +4291,7 @@ static unsigned long cam_icp_hw_mgr_mini_dump_cb(void *dst, unsigned long len, md = (struct cam_icp_hw_mini_dump_info *)dst; md->num_context = 0; hw_mgr = &icp_hw_mgr[hw_mgr_idx]; - cam_hfi_mini_dump(&md->hfi_info); + cam_hfi_mini_dump(hw_mgr->hfi_handle, &md->hfi_info); memcpy(&md->hfi_mem_info, &hw_mgr->hfi_mem, sizeof(struct icp_hfi_mem_info)); memcpy(&md->dev_info, &hw_mgr->dev_info, @@ -4360,6 +4395,7 @@ static void cam_icp_mgr_device_deinit(struct cam_icp_hw_mgr *hw_mgr) { struct cam_hw_intf *dev_intf; int i, j, dev_info_idx; + bool send_freq_info = false; for (i = 0; i < CAM_ICP_HW_MAX; i++) { for (j = 0; j < hw_mgr->hw_dev_cnt[i]; j++) { @@ -4369,7 +4405,11 @@ static void cam_icp_mgr_device_deinit(struct cam_icp_hw_mgr *hw_mgr) cam_icp_hw_dev_type_to_name(i), j); return; } - dev_intf->hw_ops.deinit(dev_intf->hw_priv, NULL, 0); + if (i == CAM_ICP_HW_ICP_V1 || i == CAM_ICP_HW_ICP_V2) + dev_intf->hw_ops.deinit(dev_intf->hw_priv, + &send_freq_info, sizeof(send_freq_info)); + else + dev_intf->hw_ops.deinit(dev_intf->hw_priv, NULL, 0); } if (CAM_ICP_IS_DEV_HW_EXIST(hw_mgr->hw_cap_mask, i) && (i >= CAM_ICP_DEV_START_IDX)) { @@ -4397,7 +4437,7 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) cam_icp_mgr_proc_shutdown(hw_mgr); - cam_hfi_deinit(); + cam_hfi_deinit(hw_mgr->hfi_handle); cam_icp_free_hfi_mem(hw_mgr); hw_mgr->icp_booted = false; @@ -4410,6 +4450,7 @@ static int cam_icp_mgr_device_init(struct cam_icp_hw_mgr *hw_mgr) { int rc = 0, i, j, dev_info_idx; struct cam_hw_intf *dev_intf = NULL; + bool send_freq_info = false; for (i = 0; i < CAM_ICP_HW_MAX; i++) { for (j = 0; j < hw_mgr->hw_dev_cnt[i]; j++) { @@ -4420,7 +4461,11 @@ static int cam_icp_mgr_device_init(struct cam_icp_hw_mgr *hw_mgr) rc = -EINVAL; goto hw_dev_deinit; } - rc = dev_intf->hw_ops.init(dev_intf->hw_priv, NULL, 0); + if (i == CAM_ICP_HW_ICP_V1 || i == CAM_ICP_HW_ICP_V2) + rc = dev_intf->hw_ops.init(dev_intf->hw_priv, + &send_freq_info, sizeof(send_freq_info)); + else + rc = dev_intf->hw_ops.init(dev_intf->hw_priv, NULL, 0); if (rc) { CAM_ERR(CAM_ICP, "Failed to init %s[%u]", cam_icp_hw_dev_type_to_name(i), j); @@ -4442,7 +4487,11 @@ hw_dev_deinit: for (; i >= 0; i--) { for (; j >= 0; j--) { dev_intf = hw_mgr->devices[i][j]; - dev_intf->hw_ops.deinit(dev_intf->hw_priv, NULL, 0); + if (i == CAM_ICP_HW_ICP_V1 || i == CAM_ICP_HW_ICP_V2) + dev_intf->hw_ops.deinit(dev_intf->hw_priv, + &send_freq_info, sizeof(send_freq_info)); + else + dev_intf->hw_ops.deinit(dev_intf->hw_priv, NULL, 0); } if (i >= CAM_ICP_DEV_START_IDX) { dev_info_idx = CAM_ICP_GET_DEV_INFO_IDX(i); @@ -4473,7 +4522,17 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) return rc; } - return cam_hfi_init(&hfi_mem, hfi_ops, icp_dev_intf->hw_priv, 0); + rc = cam_hfi_init(hw_mgr->hfi_handle, &hfi_mem, hfi_ops, + icp_dev_intf->hw_priv, 0); + if (rc) { + CAM_ERR(CAM_ICP, "Failed to init HFI rc=%d", rc); + return rc; + } + + CAM_DBG(CAM_ICP, "%s hw mgr succeed hfi init with hfi handle: %d", + hw_mgr->hw_mgr_name, hw_mgr->hfi_handle); + + return rc; } static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr) @@ -4490,6 +4549,7 @@ static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr) reinit_completion(&hw_mgr->icp_complete); CAM_DBG(CAM_ICP, "Sending HFI init command"); + rc = icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, CAM_ICP_SEND_INIT, NULL, 0); if (rc) { @@ -4552,8 +4612,7 @@ static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr) { int rc = 0; struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; - bool downloadFromResume = true; - bool send_freq_info = true; + bool downloadFromResume = true, send_freq_info; CAM_DBG(CAM_ICP, "Enter"); @@ -4567,6 +4626,7 @@ static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr) return cam_icp_mgr_hw_open_k(hw_mgr, &downloadFromResume); } + send_freq_info = true; rc = icp_dev_intf->hw_ops.init(icp_dev_intf->hw_priv, &send_freq_info, sizeof(send_freq_info)); if (rc) { @@ -4592,7 +4652,9 @@ static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr) power_collapse: __power_collapse(hw_mgr); hw_deinit: - icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, NULL, 0); + send_freq_info = false; + icp_dev_intf->hw_ops.deinit(icp_dev_intf->hw_priv, &send_freq_info, + sizeof(send_freq_info)); return rc; } @@ -4642,7 +4704,6 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) rc = cam_icp_mgr_hfi_init(hw_mgr); if (rc) { CAM_ERR(CAM_ICP, "Failed in hfi init, rc %d", rc); - dump_type = (CAM_ICP_DUMP_STATUS_REGISTERS | CAM_ICP_DUMP_CSR_REGISTERS); hw_mgr->icp_dev_intf->hw_ops.process_cmd(hw_mgr->icp_dev_intf->hw_priv, CAM_ICP_CMD_HW_REG_DUMP, &dump_type, sizeof(dump_type)); @@ -4688,7 +4749,7 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) return rc; fw_init_failed: - cam_hfi_deinit(); + cam_hfi_deinit(hw_mgr->hfi_handle); hfi_init_failed: cam_icp_mgr_proc_shutdown(hw_mgr); boot_failed: @@ -5327,7 +5388,7 @@ static int cam_icp_process_stream_settings( map_cmd_size); reinit_completion(&ctx_data->wait_complete); - rc = hfi_write_cmd(async_direct); + rc = hfi_write_cmd(hw_mgr->hfi_handle, async_direct); if (rc) { CAM_ERR(CAM_ICP, "hfi write failed rc %d", rc); goto end; @@ -6677,10 +6738,10 @@ static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) goto get_io_buf_failed; if (hw_mgr->icp_debug_type) - hfi_set_debug_level(hw_mgr->icp_debug_type, + hfi_set_debug_level(hw_mgr->hfi_handle, hw_mgr->icp_debug_type, hw_mgr->icp_dbg_lvl); - hfi_set_fw_dump_levels(hw_mgr->icp_fw_dump_lvl, + hfi_set_fw_dump_levels(hw_mgr->hfi_handle, hw_mgr->icp_fw_dump_lvl, hw_mgr->icp_fw_ramdump_lvl); rc = cam_icp_send_ubwc_cfg(hw_mgr); @@ -7303,6 +7364,62 @@ static int cam_icp_mgr_get_device_capability(struct cam_icp_hw_mgr *hw_mgr, return rc; } +static int cam_icp_mgr_register_hfi_client(struct cam_icp_hw_mgr *hw_mgr) +{ + + struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; + int hfi_handle; + int rc; + + if (!icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP device interface is NULL"); + return -EINVAL; + } + + hw_mgr->hfi_handle = HFI_HANDLE_INIT_VALUE; + rc = cam_hfi_register(&hw_mgr->hfi_handle); + if (rc) { + CAM_ERR(CAM_ICP, "Fail to register hw mgr as hfi client rc=%d", rc); + return rc; + } + + hfi_handle = hw_mgr->hfi_handle; + rc = icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, CAM_ICP_CMD_SET_HFI_HANDLE, + &hfi_handle, sizeof(hfi_handle)); + if (rc) { + CAM_ERR(CAM_ICP, "Fail to share hfi handle to ICP core rc=%d hfi hdl: %d", + rc, hfi_handle); + cam_hfi_unregister(&hw_mgr->hfi_handle); + return rc; + } + + CAM_DBG(CAM_ICP, "[%s] successfully registered as hfi client with handle: %d", + hw_mgr->hw_mgr_name, hfi_handle); + + return 0; +} + +static void cam_icp_mgr_unregister_hfi_client(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *icp_dev_intf = hw_mgr->icp_dev_intf; + int rc; + + rc = cam_hfi_unregister(&hw_mgr->hfi_handle); + if (rc) { + CAM_ERR(CAM_ICP, "Failed to unregister hfi client hdl: %d rc: %d", + hw_mgr->hfi_handle, rc); + return; + } + + if (!icp_dev_intf) { + CAM_ERR(CAM_ICP, "ICP dev intf is NULL"); + return; + } + + icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, CAM_ICP_CMD_SET_HFI_HANDLE, + &hw_mgr->hfi_handle, sizeof(hw_mgr->hfi_handle)); +} + static int cam_icp_mgr_get_hw_mgr_name(uint32_t device_idx, char *hw_mgr_name) { if (!hw_mgr_name) { @@ -7417,6 +7534,12 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, if (iommu_hdl) *iommu_hdl = hw_mgr->iommu_hdl; + rc = cam_icp_mgr_register_hfi_client(hw_mgr); + if (rc) { + CAM_ERR(CAM_ICP, "Fail to register hw mgr as hfi handle"); + goto icp_hfi_register_failed; + } + init_completion(&hw_mgr->icp_complete); cam_common_register_mini_dump_cb(cam_icp_hw_mgr_mini_dump_cb, hw_mgr->hw_mgr_name, &hw_mgr->hw_mgr_id); @@ -7433,6 +7556,8 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, return rc; icp_get_svs_clk_failed: + cam_hfi_unregister(&hw_mgr->hfi_handle); +icp_hfi_register_failed: debugfs_remove_recursive(hw_mgr->dentry); hw_mgr->dentry = NULL; icp_debugfs_create_failed: @@ -7465,6 +7590,8 @@ void cam_icp_hw_mgr_deinit(int device_idx) CAM_DBG(CAM_ICP, "hw mgr deinit: %u icp name: %s", device_idx, hw_mgr->hw_mgr_name); hw_mgr->dentry = NULL; + + cam_icp_mgr_unregister_hfi_client(hw_mgr); cam_icp_mgr_destroy_wq(hw_mgr); cam_icp_mgr_free_devs(hw_mgr); mutex_destroy(&hw_mgr->hw_mgr_mutex); diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h index 4b91a75cf4..b6cbe39730 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h @@ -60,11 +60,6 @@ /* Used for targets >= 480 and its variants */ #define CPAS_TITAN_IPE0_CAP_BIT 0x800 -#define ICP_PWR_CLP_BPS 0x00000001 -#define ICP_PWR_CLP_IPE0 0x00010000 -#define ICP_PWR_CLP_IPE1 0x00020000 -#define ICP_PWR_CLP_OFE 0x00000001 - #define CAM_ICP_CTX_STATE_FREE 0x0 #define CAM_ICP_CTX_STATE_IN_USE 0x1 #define CAM_ICP_CTX_STATE_ACQUIRED 0x2 @@ -416,6 +411,7 @@ struct cam_icp_clk_info { * @icp_resumed: Processor is powered on * @iommu_hdl: Non secure IOMMU handle * @iommu_sec_hdl: Secure IOMMU handle + * @hfi_handle: hfi handle for this ICP hw mgr * @hfi_mem: Memory for hfi * @cmd_work: Work queue for hfi commands * @msg_work: Work queue for hfi messages @@ -470,6 +466,7 @@ struct cam_icp_hw_mgr { bool icp_resumed; int32_t iommu_hdl; int32_t iommu_sec_hdl; + int32_t hfi_handle; struct icp_hfi_mem_info hfi_mem; struct cam_req_mgr_core_workq *cmd_work; struct cam_req_mgr_core_workq *msg_work; diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h index f665a84ba4..c74efb5e62 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/include/cam_icp_hw_intf.h @@ -67,6 +67,7 @@ enum cam_icp_cmd_type { CAM_ICP_CMD_HW_DUMP, CAM_ICP_CMD_HW_MINI_DUMP, CAM_ICP_CMD_HW_REG_DUMP, + CAM_ICP_CMD_SET_HFI_HANDLE, CAM_ICP_CMD_MAX, }; @@ -98,7 +99,7 @@ struct cam_icp_boot_args { }; /** - * struct cam_icp_clk_update_cmd - Payload for hw manager command + * struct cam_icp_dev_clk_update_cmd - Payload for hw manager command * * @curr_clk_rate: clk rate to HW * @clk_level: clk level corresponding to the clk rate @@ -106,10 +107,21 @@ struct cam_icp_boot_args { * updated to the given rate * @dev_pc_enable: power collpase enable flag */ -struct cam_icp_clk_update_cmd { +struct cam_icp_dev_clk_update_cmd { uint32_t curr_clk_rate; int32_t clk_level; bool dev_pc_enable; }; +/** + * struct cam_icp_ubwc_cfg_cmd - ubwc cmd to send + * + * @ubwc_cfg_dev_mask: mask to indicate which device ubwc cfg to send to fw + * @disable_ubwc_comp: flag to force disable ubwc + */ +struct cam_icp_ubwc_cfg_cmd { + uint32_t ubwc_cfg_dev_mask; + bool disable_ubwc_comp; +}; + #endif diff --git a/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_proc_common.c b/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_proc_common.c index 3eff930d12..b7728529d7 100644 --- a/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_proc_common.c +++ b/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_proc_common.c @@ -192,33 +192,77 @@ int cam_icp_proc_mini_dump(struct cam_icp_hw_dump_args *args, return 0; } -int cam_icp_proc_ubwc_configure(struct cam_icp_ubwc_cfg ubwc_cfg, - uint32_t force_disable_ubwc) +static int cam_icp_proc_validate_ubwc_cfg(struct cam_icp_ubwc_cfg *ubwc_cfg, + uint32_t ubwc_cfg_dev_mask) { + uint32_t found_ubwc_cfg_mask = ubwc_cfg->found_ubwc_cfg_mask; + + if ((ubwc_cfg_dev_mask & BIT(CAM_ICP_DEV_IPE)) && + !(found_ubwc_cfg_mask & BIT(CAM_ICP_DEV_IPE))) { + CAM_ERR(CAM_ICP, "IPE does not have UBWC cfg value"); + return -ENODATA; + } + + if ((ubwc_cfg_dev_mask & BIT(CAM_ICP_DEV_BPS)) && + !(found_ubwc_cfg_mask & BIT(CAM_ICP_DEV_BPS))) { + CAM_ERR(CAM_ICP, "BPS does not have UBWC cfg value"); + return -ENODATA; + } + + if ((ubwc_cfg_dev_mask & BIT(CAM_ICP_DEV_OFE)) && + !(found_ubwc_cfg_mask & BIT(CAM_ICP_DEV_OFE))) { + CAM_ERR(CAM_ICP, "OFE does not have UBWC cfg value"); + return -ENODATA; + } + + return 0; +} + +int cam_icp_proc_ubwc_configure(struct cam_icp_proc_ubwc_cfg_cmd *ubwc_cfg_cmd, + bool force_disable_ubwc, int hfi_handle) +{ + struct cam_icp_ubwc_cfg *ubwc_cfg; int i = 0, ddr_type, rc; - uint32_t ipe_ubwc_cfg[ICP_UBWC_CFG_MAX]; - uint32_t bps_ubwc_cfg[ICP_UBWC_CFG_MAX]; + uint32_t ipe_ubwc_cfg[ICP_UBWC_CFG_MAX] = {0}; + uint32_t bps_ubwc_cfg[ICP_UBWC_CFG_MAX] = {0}; + uint32_t ofe_ubwc_cfg[ICP_UBWC_CFG_MAX] = {0}; + + if (!ubwc_cfg_cmd) { + CAM_ERR(CAM_ICP, "ubwc config command is NULL"); + return -EINVAL; + } + + ubwc_cfg = ubwc_cfg_cmd->ubwc_cfg; + rc = cam_icp_proc_validate_ubwc_cfg(ubwc_cfg, ubwc_cfg_cmd->ubwc_cfg_dev_mask); + if (rc) { + CAM_ERR(CAM_ICP, "UBWC config failed validation rc:%d", rc); + return rc; + } ddr_type = cam_get_ddr_type(); if (ddr_type == DDR_TYPE_LPDDR5 || ddr_type == DDR_TYPE_LPDDR5X) i = 1; - ipe_ubwc_cfg[0] = ubwc_cfg.ipe_fetch[i]; - ipe_ubwc_cfg[1] = ubwc_cfg.ipe_write[i]; + ipe_ubwc_cfg[0] = ubwc_cfg->ipe_fetch[i]; + ipe_ubwc_cfg[1] = ubwc_cfg->ipe_write[i]; - bps_ubwc_cfg[0] = ubwc_cfg.bps_fetch[i]; - bps_ubwc_cfg[1] = ubwc_cfg.bps_write[i]; + bps_ubwc_cfg[0] = ubwc_cfg->bps_fetch[i]; + bps_ubwc_cfg[1] = ubwc_cfg->bps_write[i]; + + ofe_ubwc_cfg[0] = ubwc_cfg->ofe_fetch[i]; + ofe_ubwc_cfg[1] = ubwc_cfg->ofe_write[i]; if (force_disable_ubwc) { ipe_ubwc_cfg[1] &= ~CAM_ICP_UBWC_COMP_EN; bps_ubwc_cfg[1] &= ~CAM_ICP_UBWC_COMP_EN; + ofe_ubwc_cfg[1] &= ~CAM_ICP_UBWC_COMP_EN; CAM_DBG(CAM_ICP, - "Force disable UBWC compression, ipe_ubwc_cfg: 0x%x, bps_ubwc_cfg: 0x%x", - ipe_ubwc_cfg[1], bps_ubwc_cfg[1]); + "Force disable UBWC compression, ipe_ubwc_cfg: 0x%x, bps_ubwc_cfg: 0x%x ofe_ubwc_cfg: 0x%x", + ipe_ubwc_cfg[1], bps_ubwc_cfg[1], ofe_ubwc_cfg[1]); } - rc = hfi_cmd_ubwc_config_ext(ipe_ubwc_cfg, bps_ubwc_cfg); + rc = hfi_cmd_ubwc_config_ext(hfi_handle, ipe_ubwc_cfg, bps_ubwc_cfg, ofe_ubwc_cfg); if (rc) { CAM_ERR(CAM_ICP, "Failed to write UBWC configure rc=%d", rc); return rc; diff --git a/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_proc_common.h b/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_proc_common.h index 0e25570430..fb06b6f236 100644 --- a/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_proc_common.h +++ b/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_proc_common.h @@ -20,6 +20,17 @@ #define PC_POLL_DELAY_US 100 #define PC_POLL_TIMEOUT_US 10000 +/** + * struct cam_icp_proc_ubwc_cfg_cmd + * @ubwc_cfg: UBWC cfg info parsed from DT + * @ubwc_cfg_dev_mask: mask to indicate which device + * ubwc cfg to send to fw + */ +struct cam_icp_proc_ubwc_cfg_cmd { + struct cam_icp_ubwc_cfg *ubwc_cfg; + uint32_t ubwc_cfg_dev_mask; +}; + /** * @brief : Validate FW elf image */ @@ -51,7 +62,7 @@ int cam_icp_proc_mini_dump(struct cam_icp_hw_dump_args *args, /** * @brief : Update UBWC configuration for IPE and BPS */ -int cam_icp_proc_ubwc_configure(struct cam_icp_ubwc_cfg ubwc_cfg, - uint32_t force_disable_ubwc); +int cam_icp_proc_ubwc_configure(struct cam_icp_proc_ubwc_cfg_cmd *ubwc_cfg_cmd, + bool force_disable_ubwc, int hfi_handle); #endif /* _CAM_ICP_UTILS_H_ */ diff --git a/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.c b/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.c index e528703b1f..d8281cbad9 100644 --- a/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.c +++ b/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.c @@ -12,15 +12,21 @@ #include "hfi_intf.h" #include "cam_icp_soc_common.h" -static int __ubwc_config_get(struct device_node *np, char *name, uint32_t *cfg) +static int __ubwc_config_get(struct device_node *np, char *name, uint32_t *cfg, bool *ubwc_listed) { - int nconfig; - int i, rc; + int nconfig, i, rc; nconfig = of_property_count_u32_elems(np, name); - if (nconfig < 0 || nconfig > ICP_UBWC_CFG_MAX) { - CAM_ERR(CAM_ICP, "Invalid number of UBWC configs[=%d]", - nconfig); + if (nconfig < 0) { + CAM_DBG(CAM_ICP, "prop: %s is not listed", name); + *ubwc_listed = false; + return 0; + } + *ubwc_listed = true; + + if (nconfig > ICP_UBWC_CFG_MAX) { + CAM_ERR(CAM_ICP, "Invalid number of UBWC configs[=%d] MAX UBWC=%d", + nconfig, ICP_UBWC_CFG_MAX); return -EINVAL; } @@ -40,38 +46,83 @@ static int __ubwc_config_get(struct device_node *np, char *name, uint32_t *cfg) static int cam_icp_soc_ubwc_config_get(struct device_node *np, struct cam_icp_soc_info *icp_soc_info) { - struct cam_icp_ubwc_cfg *ubwc_cfg_ext = NULL; + struct cam_icp_ubwc_cfg *ubwc_cfg_ext; int rc; uint32_t dev_type; + bool ubwc_listed, ubwc_fetch_found, ubwc_write_found; dev_type = icp_soc_info->dev_type; - ubwc_cfg_ext = &icp_soc_info->uconfig.ubwc_cfg_ext; - rc = __ubwc_config_get(np, "ubwc-ipe-fetch-cfg", ubwc_cfg_ext->ipe_fetch); - if (rc) { - if (dev_type == CAM_ICP_HW_ICP_V1) { - rc = __ubwc_config_get(np, "ubwc-cfg", icp_soc_info->uconfig.ubwc_cfg); - if (rc) - return rc; + rc = __ubwc_config_get(np, "ubwc-cfg", icp_soc_info->uconfig.ubwc_cfg, + &ubwc_listed); + if (ubwc_listed) { + if (dev_type == CAM_ICP_HW_ICP_V1) icp_soc_info->is_ubwc_cfg = true; - } return rc; } - rc = __ubwc_config_get(np, "ubwc-ipe-write-cfg", - icp_soc_info->uconfig.ubwc_cfg_ext.ipe_write); + ubwc_cfg_ext = &icp_soc_info->uconfig.ubwc_cfg_ext; + rc = __ubwc_config_get(np, "ubwc-ipe-fetch-cfg", + ubwc_cfg_ext->ipe_fetch, &ubwc_fetch_found); if (rc) return rc; + rc = __ubwc_config_get(np, "ubwc-ipe-write-cfg", + ubwc_cfg_ext->ipe_write, &ubwc_write_found); + if (rc) + return rc; + + if (ubwc_fetch_found && ubwc_write_found) + ubwc_cfg_ext->found_ubwc_cfg_mask |= BIT(CAM_ICP_DEV_IPE); + else { + if (ubwc_fetch_found ^ ubwc_write_found) { + CAM_ERR(CAM_ICP, "Missing %s ipe ubwc config", + ubwc_fetch_found ? "write" : "fetch"); + return -EINVAL; + } + } + rc = __ubwc_config_get(np, "ubwc-bps-fetch-cfg", - icp_soc_info->uconfig.ubwc_cfg_ext.bps_fetch); + ubwc_cfg_ext->bps_fetch, &ubwc_fetch_found); if (rc) return rc; rc = __ubwc_config_get(np, "ubwc-bps-write-cfg", - icp_soc_info->uconfig.ubwc_cfg_ext.bps_write); + ubwc_cfg_ext->bps_write, &ubwc_write_found); + if (rc) + return rc; - return rc; + if (ubwc_fetch_found && ubwc_write_found) + ubwc_cfg_ext->found_ubwc_cfg_mask |= BIT(CAM_ICP_DEV_BPS); + else { + if (ubwc_fetch_found ^ ubwc_write_found) { + CAM_ERR(CAM_ICP, "Missing %s bps ubwc config", + ubwc_fetch_found ? "write" : "fetch"); + return -EINVAL; + } + } + + rc = __ubwc_config_get(np, "ubwc-ofe-fetch-cfg", + ubwc_cfg_ext->ofe_fetch, &ubwc_fetch_found); + if (rc) + return rc; + + rc = __ubwc_config_get(np, "ubwc-ofe-write-cfg", + ubwc_cfg_ext->ofe_write, &ubwc_write_found); + if (rc) + return rc; + + if (ubwc_fetch_found && ubwc_write_found) + ubwc_cfg_ext->found_ubwc_cfg_mask |= BIT(CAM_ICP_DEV_OFE); + else { + if (ubwc_fetch_found ^ ubwc_write_found) { + CAM_ERR(CAM_ICP, "Missing %s ofe ubwc config", + ubwc_fetch_found ? "write" : "fetch"); + return -EINVAL; + } + } + + return 0; } static inline void cam_icp_soc_qos_get(struct device_node *np, @@ -201,7 +252,7 @@ int cam_icp_soc_resources_disable(struct cam_hw_soc_info *soc_info) } int cam_icp_soc_update_clk_rate(struct cam_hw_soc_info *soc_info, - int32_t clk_level) + int32_t clk_level, int hfi_handle) { int32_t src_clk_idx = 0; int32_t clk_rate = 0; @@ -246,6 +297,6 @@ int cam_icp_soc_update_clk_rate(struct cam_hw_soc_info *soc_info, if (rc) return rc; - hfi_send_freq_info(clk_rate); + hfi_send_freq_info(hfi_handle, clk_rate); return 0; } diff --git a/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.h b/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.h index b92980f9b7..3dcfe942dc 100644 --- a/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.h +++ b/drivers/cam_icp/icp_hw/icp_proc/icp_common/cam_icp_soc_common.h @@ -21,12 +21,19 @@ * @ipe_write: UBWC configuration for IPE write. * @bps_fetch: UBWC configuration for BPS fetch. * @bps_write: UBWC configuration for BPS write. + * @ofe_fetch: UBWC configuration for ofe fetch. + * @ofe_write: UBWC configuration for ofe write. + * @found_ubwc_cfg_mask: mask to indicate which + * ubwc dev cfg found from DT */ struct cam_icp_ubwc_cfg { uint32_t ipe_fetch[ICP_UBWC_CFG_MAX]; uint32_t ipe_write[ICP_UBWC_CFG_MAX]; uint32_t bps_fetch[ICP_UBWC_CFG_MAX]; uint32_t bps_write[ICP_UBWC_CFG_MAX]; + uint32_t ofe_fetch[ICP_UBWC_CFG_MAX]; + uint32_t ofe_write[ICP_UBWC_CFG_MAX]; + uint32_t found_ubwc_cfg_mask; }; /** @@ -60,6 +67,6 @@ int cam_icp_soc_resources_enable(struct cam_hw_soc_info *soc_info); int cam_icp_soc_resources_disable(struct cam_hw_soc_info *soc_info); int cam_icp_soc_update_clk_rate(struct cam_hw_soc_info *soc_info, - int32_t clk_level); + int32_t clk_level, int hfi_handle); #endif diff --git a/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_core.c b/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_core.c index b6687b6760..18a43fa837 100644 --- a/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_core.c +++ b/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_core.c @@ -182,8 +182,8 @@ static int cam_icp_v1_fw_mini_dump(struct cam_icp_hw_dump_args *dump_args, core_info->fw_buf_len); } -int cam_icp_v1_init_hw(void *device_priv, - void *init_hw_args, uint32_t arg_size) +int cam_icp_v1_init_hw(void *device_priv, void *args, + uint32_t arg_size) { struct cam_hw_info *icp_v1_dev = device_priv; struct cam_hw_soc_info *soc_info = NULL; @@ -192,7 +192,7 @@ int cam_icp_v1_init_hw(void *device_priv, struct cam_icp_cpas_vote cpas_vote; unsigned long flags; int rc = 0; - bool send_freq_info = (init_hw_args == NULL) ? false : *((bool *)init_hw_args); + bool send_freq_info; if (!device_priv) { CAM_ERR(CAM_ICP, "Invalid cam_dev_info"); @@ -202,12 +202,14 @@ int cam_icp_v1_init_hw(void *device_priv, soc_info = &icp_v1_dev->soc_info; core_info = (struct cam_icp_v1_device_core_info *)icp_v1_dev->core_info; - if ((!soc_info) || (!core_info)) { - CAM_ERR(CAM_ICP, "soc_info: %pK core_info: %pK", - soc_info, core_info); + if ((!soc_info) || (!core_info) || (!args)) { + CAM_ERR(CAM_ICP, "soc_info: %pK core_info: %pK args: %pK", + soc_info, core_info, args); return -EINVAL; } + send_freq_info = *((bool *)args); + spin_lock_irqsave(&icp_v1_dev->hw_lock, flags); if (icp_v1_dev->hw_state == CAM_HW_STATE_POWER_UP) { spin_unlock_irqrestore(&icp_v1_dev->hw_lock, flags); @@ -256,7 +258,7 @@ int cam_icp_v1_init_hw(void *device_priv, int32_t clk_rate = 0; clk_rate = clk_get_rate(soc_info->clk[soc_info->src_clk_idx]); - hfi_send_freq_info(clk_rate); + hfi_send_freq_info(core_info->hfi_handle, clk_rate); } } @@ -269,20 +271,22 @@ error: } int cam_icp_v1_deinit_hw(void *device_priv, - void *init_hw_args, uint32_t arg_size) + void *args, uint32_t arg_size) { struct cam_hw_info *icp_v1_dev = device_priv; struct cam_hw_soc_info *soc_info = NULL; struct cam_icp_v1_device_core_info *core_info = NULL; unsigned long flags; int rc = 0; - bool send_freq_info = (init_hw_args == NULL) ? false : *((bool *)init_hw_args); + bool send_freq_info; - if (!device_priv) { - CAM_ERR(CAM_ICP, "Invalid cam_dev_info"); + if (!device_priv || !args) { + CAM_ERR(CAM_ICP, "Invalid icp hw info is %s args is %s", + CAM_IS_NULL_TO_STR(icp_v1_dev), CAM_IS_NULL_TO_STR(args)); return -EINVAL; } + send_freq_info = *((bool *)args); soc_info = &icp_v1_dev->soc_info; core_info = (struct cam_icp_v1_device_core_info *)icp_v1_dev->core_info; if ((!soc_info) || (!core_info)) { @@ -299,7 +303,7 @@ int cam_icp_v1_deinit_hw(void *device_priv, spin_unlock_irqrestore(&icp_v1_dev->hw_lock, flags); if (send_freq_info) - hfi_send_freq_info(0); + hfi_send_freq_info(core_info->hfi_handle, 0); rc = cam_icp_soc_resources_disable(soc_info); @@ -563,6 +567,44 @@ void cam_icp_v1_populate_hfi_ops(const struct hfi_ops **hfi_proc_ops) *hfi_proc_ops = &hfi_icp_v1_ops; } +static int cam_icp_v1_send_fw_init(struct cam_icp_v1_device_core_info *core_info) +{ + int rc; + + if (!core_info) { + CAM_ERR(CAM_ICP, "Invalid core info is NULL"); + return -EINVAL; + } + + rc = hfi_send_system_cmd(core_info->hfi_handle, HFI_CMD_SYS_INIT, 0, 0); + if (rc) { + CAM_ERR(CAM_ICP, "Fail to send sys init command for hfi handle: %d", + core_info->hfi_handle); + return rc; + } + + return 0; +} + +static int cam_icp_v1_pc_prep(struct cam_icp_v1_device_core_info *core_info) +{ + int rc; + + if (!core_info) { + CAM_ERR(CAM_ICP, "Invalid ICP core info is NULL"); + return -EINVAL; + } + + rc = hfi_send_system_cmd(core_info->hfi_handle, HFI_CMD_SYS_PC_PREP, 0, 0); + if (rc) { + CAM_ERR(CAM_ICP, "Fail to send PC collapse command for hfi handle: %d", + core_info->hfi_handle); + return rc; + } + + return 0; +} + int cam_icp_v1_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -599,13 +641,11 @@ int cam_icp_v1_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_icp_v1_power_resume(icp_v1_dev, *((bool *)cmd_args)); break; case CAM_ICP_SEND_INIT: - hfi_send_system_cmd(HFI_CMD_SYS_INIT, 0, 0); + rc = cam_icp_v1_send_fw_init(core_info); break; - case CAM_ICP_CMD_PC_PREP: - hfi_send_system_cmd(HFI_CMD_SYS_PC_PREP, 0, 0); + rc = cam_icp_v1_pc_prep(core_info); break; - case CAM_ICP_CMD_VOTE_CPAS: { struct cam_icp_cpas_vote *cpas_vote = cmd_args; @@ -618,6 +658,23 @@ int cam_icp_v1_process_cmd(void *device_priv, uint32_t cmd_type, break; } + case CAM_ICP_CMD_SET_HFI_HANDLE: { + if (!core_info || !cmd_args) { + CAM_ERR(CAM_ICP, "Core info is %s and args is %s", + CAM_IS_NULL_TO_STR(core_info), CAM_IS_NULL_TO_STR(cmd_args)); + return -EINVAL; + } + + if (arg_size != sizeof(int)) { + CAM_ERR(CAM_ICP, "Invalid set hfi handle command arg size:%u", + arg_size); + return -EINVAL; + } + + core_info->hfi_handle = *((int *)cmd_args); + break; + } + case CAM_ICP_CMD_CPAS_START: { struct cam_icp_cpas_vote *cpas_vote = cmd_args; @@ -642,7 +699,8 @@ int cam_icp_v1_process_cmd(void *device_priv, uint32_t cmd_type, } break; case CAM_ICP_CMD_UBWC_CFG: { - uint32_t disable_ubwc_comp; + struct cam_icp_ubwc_cfg_cmd *ubwc_cmd = cmd_args; + struct cam_icp_proc_ubwc_cfg_cmd ubwc_proc_cmd; icp_soc_info = soc_info->soc_private; if (!icp_soc_info) { @@ -651,32 +709,44 @@ int cam_icp_v1_process_cmd(void *device_priv, uint32_t cmd_type, } if (!cmd_args) { - CAM_ERR(CAM_ICP, "Invalid args"); + CAM_ERR(CAM_ICP, "Invalid ubwc cmd args is NULL"); + return -EINVAL; + } + + if (arg_size != sizeof(struct cam_icp_ubwc_cfg_cmd)) { + CAM_ERR(CAM_ICP, "Invalid ubwc cmd size:%u", arg_size); return -EINVAL; } - disable_ubwc_comp = *((uint32_t *)cmd_args); if (icp_soc_info->is_ubwc_cfg) - rc = hfi_cmd_ubwc_config(icp_soc_info->uconfig.ubwc_cfg); - else - rc = cam_icp_proc_ubwc_configure(icp_soc_info->uconfig.ubwc_cfg_ext, - disable_ubwc_comp); - + rc = hfi_cmd_ubwc_config(core_info->hfi_handle, + icp_soc_info->uconfig.ubwc_cfg); + else { + ubwc_proc_cmd.ubwc_cfg = &icp_soc_info->uconfig.ubwc_cfg_ext; + rc = cam_icp_proc_ubwc_configure(&ubwc_proc_cmd, + ubwc_cmd->disable_ubwc_comp, core_info->hfi_handle); + } break; } case CAM_ICP_CMD_CLK_UPDATE: { int32_t clk_level = 0; struct cam_ahb_vote ahb_vote; - if (!cmd_args) { - CAM_ERR(CAM_ICP, "Invalid args"); + if (!cmd_args || !core_info) { + CAM_ERR(CAM_ICP, "Invalid args: core info is %s cmd args is %s", + CAM_IS_NULL_TO_STR(core_info), CAM_IS_NULL_TO_STR(cmd_args)); + return -EINVAL; + } + + if (arg_size != sizeof(int32_t)) { + CAM_ERR(CAM_ICP, "Invalid icp clock update command"); return -EINVAL; } clk_level = *((int32_t *)cmd_args); CAM_DBG(CAM_ICP, "Update ICP clock to level [%d]", clk_level); - rc = cam_icp_soc_update_clk_rate(soc_info, clk_level); + rc = cam_icp_soc_update_clk_rate(soc_info, clk_level, core_info->hfi_handle); if (rc) CAM_ERR(CAM_ICP, "Failed to update clk to level: %d rc: %d", diff --git a/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_core.h b/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_core.h index 16fffba643..296d4b8962 100644 --- a/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_core.h +++ b/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_core.h @@ -38,6 +38,7 @@ * @icp_v1_acquire: Acquire information of ICP_V1 * @irq_cb: IRQ callback * @cpas_handle: CPAS handle for ICP_V1 + * @hfi_handle: hfi handle for ICP V1 * @hw_version: hw version of icp v1 processor * @cpas_start: state variable for cpas */ @@ -49,6 +50,7 @@ struct cam_icp_v1_device_core_info { uint64_t fw_buf_len; struct cam_icp_irq_cb irq_cb; uint32_t cpas_handle; + int32_t hfi_handle; bool cpas_start; }; diff --git a/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_dev.c b/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_dev.c index dbf40bbc71..579383626f 100644 --- a/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_dev.c +++ b/drivers/cam_icp/icp_hw/icp_proc/icp_v1_hw/cam_icp_v1_dev.c @@ -175,6 +175,7 @@ static int cam_icp_v1_component_bind(struct device *dev, CAM_ERR(CAM_ICP, "icp_v1 cpas registration failed"); goto cpas_reg_failed; } + core_info->hfi_handle = HFI_HANDLE_INIT_VALUE; icp_v1_dev->hw_state = CAM_HW_STATE_POWER_DOWN; mutex_init(&icp_v1_dev->hw_mutex); spin_lock_init(&icp_v1_dev->hw_lock); diff --git a/drivers/cam_icp/icp_hw/icp_proc/icp_v2_hw/cam_icp_v2_core.c b/drivers/cam_icp/icp_hw/icp_proc/icp_v2_hw/cam_icp_v2_core.c index 96629786b4..a0143ef756 100644 --- a/drivers/cam_icp/icp_hw/icp_proc/icp_v2_hw/cam_icp_v2_core.c +++ b/drivers/cam_icp/icp_hw/icp_proc/icp_v2_hw/cam_icp_v2_core.c @@ -36,16 +36,34 @@ static const struct hfi_ops hfi_icp_v2_ops = { .iface_addr = cam_icp_v2_iface_addr, }; -static int cam_icp_v2_ubwc_configure(struct cam_hw_soc_info *soc_info) +static int cam_icp_v2_ubwc_configure(struct cam_hw_soc_info *soc_info, + struct cam_icp_v2_core_info *core_info, void *args, uint32_t arg_size) { struct cam_icp_soc_info *soc_priv; + struct cam_icp_ubwc_cfg_cmd *ubwc_cmd = args; + struct cam_icp_proc_ubwc_cfg_cmd ubwc_proc_cmd; - if (!soc_info) + if (!soc_info || !core_info || !args) { + CAM_ERR(CAM_ICP, + "Invalid args: soc info is %s core info is %s cmd args is %s", + CAM_IS_NULL_TO_STR(soc_info), CAM_IS_NULL_TO_STR(core_info), + CAM_IS_NULL_TO_STR(args)); return -EINVAL; + } + + if (arg_size != sizeof(struct cam_icp_ubwc_cfg_cmd)) { + CAM_ERR(CAM_ICP, "Invalid ubwc cfg arg size: %u", + arg_size); + return -EINVAL; + } soc_priv = soc_info->soc_private; - return cam_icp_proc_ubwc_configure(soc_priv->uconfig.ubwc_cfg_ext, 0); + ubwc_proc_cmd.ubwc_cfg = &soc_priv->uconfig.ubwc_cfg_ext; + ubwc_proc_cmd.ubwc_cfg_dev_mask = ubwc_cmd->ubwc_cfg_dev_mask; + + return cam_icp_proc_ubwc_configure(&ubwc_proc_cmd, + ubwc_cmd->disable_ubwc_comp, core_info->hfi_handle); } static int cam_icp_v2_cpas_vote(struct cam_icp_v2_core_info *core_info, @@ -187,15 +205,26 @@ static int cam_icp_v2_cpas_stop(struct cam_icp_v2_core_info *core_info) int cam_icp_v2_hw_init(void *priv, void *args, uint32_t arg_size) { struct cam_hw_info *icp_v2 = priv; + struct cam_icp_v2_core_info *core_info; unsigned long flags; int rc; - bool send_freq_info = (args == NULL) ? false : *((bool *)args); + bool send_freq_info; - if (!icp_v2) { - CAM_ERR(CAM_ICP, "ICP device info cannot be NULL"); + if (!icp_v2 || !args) { + CAM_ERR(CAM_ICP, + "Invalid parameters: icp hw info is %s args is %s", + CAM_IS_NULL_TO_STR(icp_v2), CAM_IS_NULL_TO_STR(args)); return -EINVAL; } + if (arg_size != sizeof(bool)) { + CAM_ERR(CAM_ICP, "Invalid hw init cmd args"); + return -EINVAL; + } + + send_freq_info = *((bool *)args); + core_info = icp_v2->core_info; + spin_lock_irqsave(&icp_v2->hw_lock, flags); if (icp_v2->hw_state == CAM_HW_STATE_POWER_UP) { spin_unlock_irqrestore(&icp_v2->hw_lock, flags); @@ -216,7 +245,7 @@ int cam_icp_v2_hw_init(void *priv, void *args, uint32_t arg_size) int32_t clk_rate = 0; clk_rate = clk_get_rate(icp_v2->soc_info.clk[icp_v2->soc_info.src_clk_idx]); - hfi_send_freq_info(clk_rate); + hfi_send_freq_info(core_info->hfi_handle, clk_rate); } } @@ -231,18 +260,29 @@ soc_fail: return rc; } -int cam_icp_v2_hw_deinit(void *priv, void *args, uint32_t arg_size) +int cam_icp_v2_hw_deinit(void *priv, void *args, + uint32_t arg_size) { struct cam_hw_info *icp_v2_info = priv; + struct cam_icp_v2_core_info *core_info; unsigned long flags; int rc; - bool send_freq_info = (args == NULL) ? false : *((bool *)args); + bool send_freq_info; - if (!icp_v2_info) { - CAM_ERR(CAM_ICP, "ICP device info cannot be NULL"); + if (!icp_v2_info || !args) { + CAM_ERR(CAM_ICP, "ICP device info is %s cmd args is %s", + CAM_IS_NULL_TO_STR(icp_v2_info), CAM_IS_NULL_TO_STR(args)); return -EINVAL; } + if (arg_size != sizeof(bool)) { + CAM_ERR(CAM_ICP, "Invalid hw deinit cmd args"); + return -EINVAL; + } + + send_freq_info = *((bool *)args); + core_info = icp_v2_info->core_info; + spin_lock_irqsave(&icp_v2_info->hw_lock, flags); if (icp_v2_info->hw_state == CAM_HW_STATE_POWER_DOWN) { spin_unlock_irqrestore(&icp_v2_info->hw_lock, flags); @@ -251,7 +291,7 @@ int cam_icp_v2_hw_deinit(void *priv, void *args, uint32_t arg_size) spin_unlock_irqrestore(&icp_v2_info->hw_lock, flags); if (send_freq_info) - hfi_send_freq_info(0); + hfi_send_freq_info(core_info->hfi_handle, 0); rc = cam_icp_soc_resources_disable(&icp_v2_info->soc_info); if (rc) @@ -800,15 +840,15 @@ static inline int cam_icp_v2_download_fw(struct cam_hw_info *icp_v2_info, } static int __cam_icp_v2_update_clk_rate(struct cam_hw_info *icp_v2_info, - int32_t *clk_lvl) + void *args, uint32_t arg_size) { int32_t clk_level = 0, rc; struct cam_ahb_vote ahb_vote; struct cam_icp_v2_core_info *core_info = NULL; struct cam_hw_soc_info *soc_info = NULL; - if (!clk_lvl) { - CAM_ERR(CAM_ICP, "Invalid args"); + if (!args) { + CAM_ERR(CAM_ICP, "Invalid args is NULL"); return -EINVAL; } @@ -819,10 +859,15 @@ static int __cam_icp_v2_update_clk_rate(struct cam_hw_info *icp_v2_info, return -EINVAL; } - clk_level = *((int32_t *)clk_lvl); + if (arg_size != sizeof(int32_t)) { + CAM_ERR(CAM_ICP, "Invalid icp update clk args"); + return -EINVAL; + } + + clk_level = *((int32_t *)args); CAM_DBG(CAM_ICP, "Update ICP clock to level [%d]", clk_level); - rc = cam_icp_soc_update_clk_rate(soc_info, clk_level); + rc = cam_icp_soc_update_clk_rate(soc_info, clk_level, core_info->hfi_handle); if (rc) CAM_WARN(CAM_ICP, "Failed to update clk to level: %d rc: %d", @@ -851,6 +896,64 @@ static int __cam_icp_v2_fw_mini_dump(struct cam_icp_v2_core_info *core_info, core_info->fw_params.fw_buf_len); } +static int cam_icp_v2_send_fw_init(struct cam_icp_v2_core_info *core_info) +{ + int rc; + + if (!core_info) { + CAM_ERR(CAM_ICP, "Core info is NULL"); + return -EINVAL; + } + + rc = hfi_send_system_cmd(core_info->hfi_handle, HFI_CMD_SYS_INIT, 0, 0); + if (rc) { + CAM_ERR(CAM_ICP, "Fail to send sys init command for hfi handle: %d", + core_info->hfi_handle); + return rc; + } + + return 0; +} + +static int cam_icp_v2_pc_prep(struct cam_icp_v2_core_info *core_info) +{ + int rc; + + if (!core_info) { + CAM_ERR(CAM_ICP, "Invalid core info is NULL"); + return -EINVAL; + } + + rc = hfi_send_system_cmd(core_info->hfi_handle, HFI_CMD_SYS_PC_PREP, 0, 0); + if (rc) { + CAM_ERR(CAM_ICP, "Fail to send PC collapse command for hfi handle: %d", + core_info->hfi_handle); + return rc; + } + + return 0; +} + +int cam_icp_v2_set_hfi_handle(struct cam_icp_v2_core_info *core_info, + void *args, uint32_t arg_size) +{ + if (!core_info || !args) { + CAM_ERR(CAM_ICP, "Core info is %s and args is %s", + CAM_IS_NULL_TO_STR(core_info), CAM_IS_NULL_TO_STR(args)); + return -EINVAL; + } + + if (arg_size != sizeof(int)) { + CAM_ERR(CAM_ICP, "Invalid set hfi handle command arg size:%u", + arg_size); + return -EINVAL; + } + + core_info->hfi_handle = *((int *)args); + + return 0; +} + int cam_icp_v2_process_cmd(void *priv, uint32_t cmd_type, void *args, uint32_t arg_size) { @@ -863,6 +966,9 @@ int cam_icp_v2_process_cmd(void *priv, uint32_t cmd_type, } switch (cmd_type) { + case CAM_ICP_CMD_SET_HFI_HANDLE: + rc = cam_icp_v2_set_hfi_handle(icp_v2_info->core_info, args, arg_size); + break; case CAM_ICP_CMD_PROC_SHUTDOWN: rc = cam_icp_v2_shutdown(icp_v2_info); break; @@ -885,18 +991,17 @@ int cam_icp_v2_process_cmd(void *priv, uint32_t cmd_type, rc = cam_icp_v2_cpas_stop(icp_v2_info->core_info); break; case CAM_ICP_CMD_UBWC_CFG: - rc = cam_icp_v2_ubwc_configure(&icp_v2_info->soc_info); + rc = cam_icp_v2_ubwc_configure(&icp_v2_info->soc_info, + icp_v2_info->core_info, args, arg_size); break; case CAM_ICP_SEND_INIT: - hfi_send_system_cmd(HFI_CMD_SYS_INIT, 0, 0); - rc = 0; + rc = cam_icp_v2_send_fw_init(icp_v2_info->core_info); break; case CAM_ICP_CMD_PC_PREP: - hfi_send_system_cmd(HFI_CMD_SYS_PC_PREP, 0, 0); - rc = 0; + rc = cam_icp_v2_pc_prep(icp_v2_info->core_info); break; case CAM_ICP_CMD_CLK_UPDATE: { - rc = __cam_icp_v2_update_clk_rate(icp_v2_info, args); + rc = __cam_icp_v2_update_clk_rate(icp_v2_info, args, arg_size); break; } case CAM_ICP_CMD_HW_DUMP: @@ -1018,6 +1123,7 @@ int cam_icp_v2_test_irq_line(void *priv) struct cam_icp_v2_core_info *core_info = NULL; void __iomem *irq_membase; unsigned long rem_jiffies; + bool send_freq_info = false; if (!icp_v2_info) { CAM_ERR(CAM_ICP, "invalid ICP device info"); @@ -1042,7 +1148,7 @@ int cam_icp_v2_test_irq_line(void *priv) CAM_ERR(CAM_ICP, "ICP IRQ verification timed out"); cam_io_w_mb(0, irq_membase + core_info->hw_info->ob_irq_mask); - cam_icp_v2_hw_deinit(priv, NULL, 0); + cam_icp_v2_hw_deinit(priv, &send_freq_info, sizeof(send_freq_info)); core_info->is_irq_test = false; @@ -1192,5 +1298,7 @@ int cam_icp_v2_core_init( rc = -EINVAL; } + core_info->hfi_handle = HFI_HANDLE_INIT_VALUE; + return rc; } diff --git a/drivers/cam_icp/icp_hw/icp_proc/icp_v2_hw/cam_icp_v2_core.h b/drivers/cam_icp/icp_hw/icp_proc/icp_v2_hw/cam_icp_v2_core.h index 2ba1d9d057..0075239cf5 100644 --- a/drivers/cam_icp/icp_hw/icp_proc/icp_v2_hw/cam_icp_v2_core.h +++ b/drivers/cam_icp/icp_hw/icp_proc/icp_v2_hw/cam_icp_v2_core.h @@ -33,6 +33,7 @@ struct cam_icp_v2_core_info { struct cam_icp_v2_hw_info *hw_info; int32_t reg_base_idx[ICP_V2_BASE_MAX]; uint32_t cpas_handle; + int hfi_handle; enum cam_icp_v2_reg_base irq_regbase_idx; struct { const struct firmware *fw_elf; diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c index 16be391e8b..dd06ba6cb9 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -413,7 +413,7 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_ipe_handle_resume(ipe_dev); break; case CAM_ICP_DEV_CMD_UPDATE_CLK: { - struct cam_icp_clk_update_cmd *clk_upd_cmd = cmd_args; + struct cam_icp_dev_clk_update_cmd *clk_upd_cmd = cmd_args; struct cam_ahb_vote ahb_vote; uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; int32_t clk_level = 0, err = 0; diff --git a/drivers/cam_icp/icp_hw/ofe_hw/ofe_core.c b/drivers/cam_icp/icp_hw/ofe_hw/ofe_core.c index 54db513926..5d91e2dc13 100644 --- a/drivers/cam_icp/icp_hw/ofe_hw/ofe_core.c +++ b/drivers/cam_icp/icp_hw/ofe_hw/ofe_core.c @@ -417,7 +417,7 @@ int cam_ofe_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_ofe_handle_resume(ofe_dev); break; case CAM_ICP_DEV_CMD_UPDATE_CLK: { - struct cam_icp_clk_update_cmd *clk_upd_cmd = cmd_args; + struct cam_icp_dev_clk_update_cmd *clk_upd_cmd = cmd_args; struct cam_ahb_vote ahb_vote; uint32_t clk_rate = clk_upd_cmd->curr_clk_rate; int32_t clk_level = 0, err = 0;