diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index 7759461de4..0607b2db73 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -146,6 +146,15 @@ int cam_hfi_unregister(int *client_handle); */ int hfi_get_hw_caps(void *query_caps); +/** + * hfi_get_hw_caps_v2() - hardware capabilities from firmware, used for v2 query cap + * @client_handle: client handle + * @query_caps: holds query information from hfi + * + * Returns success(zero)/failure(non zero) + */ +int hfi_get_hw_caps_v2(int client_handle, void *query_caps); + /** * hfi_send_system_cmd() - send hfi system command to firmware * @client_handle: client handle diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index a3b734550b..4629ede2d1 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -283,6 +283,7 @@ struct hfi_qtbl { * @msg_q_state: State of message queue * @priv: device private data * @dbg_lvl: debug level set to FW + * @fw_version: firmware version * @client_name: hfi client's name */ struct hfi_info { @@ -298,6 +299,7 @@ struct hfi_info { bool msg_q_state; void *priv; u64 dbg_lvl; + uint32_t fw_version; char client_name[HFI_CLIENT_NAME_LEN]; }; diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 60915a1402..368676a8eb 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -759,12 +759,38 @@ int hfi_get_hw_caps(void *query_buf) return 0; } +int hfi_get_hw_caps_v2(int client_handle, void *query_buf) +{ + struct cam_icp_query_cap_cmd_v2 *query_cmd = NULL; + struct hfi_info *hfi; + 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 (!query_buf) { + CAM_ERR(CAM_HFI, "[%s] query cap buf is NULL", hfi->client_name); + return -EINVAL; + } + + query_cmd = (struct cam_icp_query_cap_cmd_v2 *)query_buf; + query_cmd->fw_version.major = (hfi->fw_version & 0xFF000000) >> 24; + query_cmd->fw_version.minor = (hfi->fw_version & 0x00FF0000) >> 16; + query_cmd->fw_version.revision = (hfi->fw_version & 0xFFFF); + + return 0; +} + 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; + uint32_t status = 0; void __iomem *icp_base = NULL; rc = hfi_get_client_info(client_handle, &hfi); @@ -793,9 +819,8 @@ int cam_hfi_resume(int client_handle) hfi_irq_enable(hfi); - fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); - CAM_DBG(CAM_HFI, "[%s] hfi hdl: %d fw version : [%x]", - hfi->client_name, client_handle, fw_version); + CAM_DBG(CAM_HFI, "[%s] hfi hdl: %d fw version : [0x%x]", + hfi->client_name, client_handle, hfi->fw_version); hfi_mem = &hfi->map; cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR); @@ -1098,8 +1123,9 @@ int cam_hfi_init(int client_handle, struct hfi_mem_info *hfi_mem, goto regions_fail; } - CAM_DBG(CAM_HFI, "ICP fw version: 0x%x", - cam_io_r(icp_base + HFI_REG_FW_VERSION)); + hfi->fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); + CAM_DBG(CAM_HFI, "[%s] ICP fw version: 0x%x", + hfi->client_name, hfi->fw_version); hfi->cmd_q_state = true; hfi->msg_q_state = true; 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 ba89aa96eb..5724da8e9e 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 @@ -7140,6 +7140,7 @@ static int cam_icp_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args) int rc = 0; struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; struct cam_query_cap_cmd *query_cap = hw_caps_args; + struct cam_icp_query_cap_cmd icp_caps; if ((!hw_mgr_priv) || (!hw_caps_args)) { CAM_ERR(CAM_ICP, "Invalid params: %pK %pK", hw_mgr_priv, hw_caps_args); @@ -7148,31 +7149,128 @@ static int cam_icp_mgr_get_hw_caps(void *hw_mgr_priv, void *hw_caps_args) if (sizeof(struct cam_icp_query_cap_cmd) != query_cap->size) { CAM_ERR(CAM_ICP, - "Input query cap size:%u does not match expected query cap size: %u", - query_cap->size, sizeof(struct cam_icp_query_cap_cmd)); + "[%s] Input query cap size:%u does not match expected query cap size: %u", + hw_mgr->hw_mgr_name, query_cap->size, + sizeof(struct cam_icp_query_cap_cmd)); return -EFAULT; } mutex_lock(&hw_mgr->hw_mgr_mutex); - if (copy_from_user(&hw_mgr->icp_caps, + if (copy_from_user(&icp_caps, u64_to_user_ptr(query_cap->caps_handle), sizeof(struct cam_icp_query_cap_cmd))) { - CAM_ERR(CAM_ICP, "[%s] copy_from_user failed", hw_mgr->hw_mgr_name); + CAM_ERR(CAM_ICP, "[%s] copy from_user failed", hw_mgr->hw_mgr_name); rc = -EFAULT; goto end; } - rc = hfi_get_hw_caps(&hw_mgr->icp_caps); + rc = hfi_get_hw_caps(&icp_caps); if (rc) { CAM_ERR(CAM_ICP, "[%s] Fail to get hfi caps", hw_mgr->hw_mgr_name); goto end; } - hw_mgr->icp_caps.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl; - hw_mgr->icp_caps.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl; + icp_caps.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl; + icp_caps.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl; if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle), - &hw_mgr->icp_caps, sizeof(struct cam_icp_query_cap_cmd))) { + &icp_caps, sizeof(struct cam_icp_query_cap_cmd))) { + CAM_ERR(CAM_ICP, "[%s] copy_to_user failed", hw_mgr->hw_mgr_name); + rc = -EFAULT; + } +end: + mutex_unlock(&hw_mgr->hw_mgr_mutex); + return rc; +} + +static int cam_icp_mgr_get_hw_caps_v2(void *hw_mgr_priv, void *hw_caps_args) +{ + int rc = 0; + struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_query_cap_cmd *query_cap = hw_caps_args; + struct cam_icp_query_cap_cmd_v2 query_cmd; + uint32_t supported_hw_dev, num_supported_device = 0; + int i; + + if ((!hw_mgr_priv) || (!hw_caps_args)) { + CAM_ERR(CAM_ICP, "Invalid params: %pK %pK", + hw_mgr_priv, hw_caps_args); + return -EINVAL; + } + + if (sizeof(struct cam_icp_query_cap_cmd_v2) != query_cap->size) { + CAM_ERR(CAM_ICP, + "[%s] Input query cap size:%u does not match expected query cap size: %ud", + hw_mgr->hw_mgr_name, query_cap->size, + sizeof(struct cam_icp_query_cap_cmd_v2)); + return -EFAULT; + } + + mutex_lock(&hw_mgr->hw_mgr_mutex); + if (copy_from_user(&query_cmd, u64_to_user_ptr(query_cap->caps_handle), + sizeof(struct cam_icp_query_cap_cmd_v2))) { + CAM_ERR(CAM_ICP, "[%s] copy from user failed", hw_mgr->hw_mgr_name); + rc = -EFAULT; + goto end; + } + memset(&query_cmd.dev_info, 0, + (CAM_ICP_MAX_NUM_OF_DEV_TYPES * sizeof(struct cam_icp_device_info))); + + for (i = 0; i < CAM_ICP_HW_MAX; i++) { + if (!CAM_ICP_IS_DEV_HW_EXIST(hw_mgr->hw_cap_mask, i)) + continue; + + switch (i) { + case CAM_ICP_HW_ICP_V1: + fallthrough; + case CAM_ICP_HW_ICP_V2: + supported_hw_dev = CAM_ICP_DEV_TYPE_ICP; + break; + case CAM_ICP_DEV_IPE: + supported_hw_dev = CAM_ICP_DEV_TYPE_IPE; + break; + case CAM_ICP_DEV_BPS: + supported_hw_dev = CAM_ICP_DEV_TYPE_BPS; + break; + case CAM_ICP_DEV_OFE: + supported_hw_dev = CAM_ICP_DEV_TYPE_OFE; + break; + default: + CAM_ERR(CAM_ICP, "[%s] Invalid icp hw type: %u", + hw_mgr->hw_mgr_name, i); + rc = -EBADSLT; + goto end; + } + + if (num_supported_device >= CAM_ICP_MAX_NUM_OF_DEV_TYPES) { + CAM_ERR(CAM_ICP, + "[%s] number of supported hw devices:%u exceeds maximum number of devices supported by query cap struct: %u", + hw_mgr->hw_mgr_name, num_supported_device, + CAM_ICP_MAX_NUM_OF_DEV_TYPES); + rc = -EFAULT; + goto end; + } + + query_cmd.dev_info[num_supported_device].dev_type = supported_hw_dev; + query_cmd.dev_info[num_supported_device].num_devices = hw_mgr->hw_dev_cnt[i]; + + num_supported_device++; + } + + query_cmd.num_dev_info = num_supported_device; + + rc = hfi_get_hw_caps_v2(hw_mgr->hfi_handle, &query_cmd); + if (rc) { + CAM_ERR(CAM_ICP, "[%s] Fail to get hfi caps rc:%d", + hw_mgr->hw_mgr_name, rc); + goto end; + } + + query_cmd.dev_iommu_handle.non_secure = hw_mgr->iommu_hdl; + query_cmd.dev_iommu_handle.secure = hw_mgr->iommu_sec_hdl; + + if (copy_to_user(u64_to_user_ptr(query_cap->caps_handle), + &query_cmd, sizeof(struct cam_icp_query_cap_cmd_v2))) { CAM_ERR(CAM_ICP, "[%s] copy_to_user failed", hw_mgr->hw_mgr_name); rc = -EFAULT; } @@ -7713,6 +7811,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, hw_mgr_intf->hw_mgr_priv = hw_mgr; hw_mgr_intf->hw_get_caps = cam_icp_mgr_get_hw_caps; + hw_mgr_intf->hw_get_caps_v2 = cam_icp_mgr_get_hw_caps_v2; hw_mgr_intf->hw_acquire = cam_icp_mgr_acquire_hw; hw_mgr_intf->hw_release = cam_icp_mgr_release_hw; hw_mgr_intf->hw_prepare_update = cam_icp_mgr_prepare_hw_update; 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 90d7701781..fa173e0833 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 @@ -408,7 +408,6 @@ struct cam_icp_clk_info { * @icp_dev_intf: ICP device interface * @hw_dev_cnt: count number of each hw type * @ctx_data: Context data - * @icp_caps: ICP capabilities * @mini_dump_cb: Mini dump cb * @hw_mgr_name: name of the hw mgr * @hw_mgr_id: ID of the hw mgr, equivalent to hw mgr index @@ -462,7 +461,6 @@ struct cam_icp_hw_mgr { struct cam_hw_intf *icp_dev_intf; uint32_t hw_dev_cnt[CAM_ICP_HW_MAX]; struct cam_icp_hw_ctx_data ctx_data[CAM_ICP_CTX_MAX]; - struct cam_icp_query_cap_cmd icp_caps; cam_icp_mini_dump_cb mini_dump_cb; char hw_mgr_name[CAM_ICP_HW_MGR_NAME_SIZE]; uint32_t hw_mgr_id;