diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index edfc42a4f2..d8f18a8220 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1747,6 +1747,7 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv, struct cam_hw_info *cpas_hw; struct cam_cpas *cpas_core; struct cam_cpas_hw_caps *hw_caps; + struct cam_cpas_private_soc *soc_private; if (!hw_priv || !get_hw_cap_args) { CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", @@ -1763,9 +1764,16 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv, cpas_hw = (struct cam_hw_info *)hw_priv; cpas_core = (struct cam_cpas *) cpas_hw->core_info; hw_caps = (struct cam_cpas_hw_caps *)get_hw_cap_args; - *hw_caps = cpas_core->hw_caps; + /*Extract Fuse Info*/ + soc_private = (struct cam_cpas_private_soc *) + cpas_hw->soc_info.soc_private; + + hw_caps->fuse_info = soc_private->fuse_info; + CAM_INFO(CAM_CPAS, "fuse info->num_fuses %d", + hw_caps->fuse_info.num_fuses); + return 0; } diff --git a/drivers/cam_cpas/cam_cpas_hw_intf.h b/drivers/cam_cpas/cam_cpas_hw_intf.h index 0964374080..c1e81f2a76 100644 --- a/drivers/cam_cpas/cam_cpas_hw_intf.h +++ b/drivers/cam_cpas/cam_cpas_hw_intf.h @@ -114,6 +114,7 @@ struct cam_cpas_hw_cmd_stop { * @camera_version: Camera version * @cpas_version: CPAS version * @camera_capability: Camera hw capabilities + * @fuse_info: Fuse information * */ struct cam_cpas_hw_caps { @@ -121,6 +122,7 @@ struct cam_cpas_hw_caps { struct cam_hw_version camera_version; struct cam_hw_version cpas_version; uint32_t camera_capability; + struct cam_cpas_fuse_info fuse_info; }; int cam_cpas_hw_probe(struct platform_device *pdev, diff --git a/drivers/cam_cpas/cam_cpas_intf.c b/drivers/cam_cpas/cam_cpas_intf.c index ddbb3bb2ef..d75c51488e 100644 --- a/drivers/cam_cpas/cam_cpas_intf.c +++ b/drivers/cam_cpas/cam_cpas_intf.c @@ -173,7 +173,8 @@ int cam_cpas_get_cpas_hw_version(uint32_t *hw_version) int cam_cpas_get_hw_info(uint32_t *camera_family, struct cam_hw_version *camera_version, struct cam_hw_version *cpas_version, - uint32_t *cam_caps) + uint32_t *cam_caps, + struct cam_cpas_fuse_info *cam_fuse_info) { if (!CAM_CPAS_INTF_INITIALIZED()) { CAM_ERR(CAM_CPAS, "cpas intf not initialized"); @@ -186,10 +187,16 @@ int cam_cpas_get_hw_info(uint32_t *camera_family, return -EINVAL; } - *camera_family = g_cpas_intf->hw_caps.camera_family; + *camera_family = g_cpas_intf->hw_caps.camera_family; *camera_version = g_cpas_intf->hw_caps.camera_version; - *cpas_version = g_cpas_intf->hw_caps.cpas_version; - *cam_caps = g_cpas_intf->hw_caps.camera_capability; + *cpas_version = g_cpas_intf->hw_caps.cpas_version; + *cam_caps = g_cpas_intf->hw_caps.camera_capability; + if (cam_fuse_info) + *cam_fuse_info = g_cpas_intf->hw_caps.fuse_info; + + CAM_DBG(CAM_CPAS, "Family %d, version %d.%d cam_caps %d", + *camera_family, camera_version->major, + camera_version->minor, *cam_caps); return 0; } @@ -529,7 +536,32 @@ int cam_cpas_subdev_cmd(struct cam_cpas_intf *cpas_intf, rc = cam_cpas_get_hw_info(&query.camera_family, &query.camera_version, &query.cpas_version, - &query.reserved); + &query.reserved, NULL); + if (rc) + break; + + rc = copy_to_user(u64_to_user_ptr(cmd->handle), &query, + sizeof(query)); + if (rc) + CAM_ERR(CAM_CPAS, "Failed in copy to user, rc=%d", rc); + + break; + } + case CAM_QUERY_CAP_V2: { + struct cam_cpas_query_cap_v2 query; + + rc = copy_from_user(&query, u64_to_user_ptr(cmd->handle), + sizeof(query)); + if (rc) { + CAM_ERR(CAM_CPAS, "Failed in copy from user, rc=%d", + rc); + break; + } + + rc = cam_cpas_get_hw_info(&query.camera_family, + &query.camera_version, &query.cpas_version, + &query.reserved, + &query.fuse_info); if (rc) break; @@ -729,6 +761,7 @@ static int cam_cpas_dev_component_bind(struct device *dev, hw_intf = g_cpas_intf->hw_intf; hw_caps = &g_cpas_intf->hw_caps; + if (hw_intf->hw_ops.get_hw_caps) { rc = hw_intf->hw_ops.get_hw_caps(hw_intf->hw_priv, hw_caps, sizeof(struct cam_cpas_hw_caps)); diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index a7550a3974..f569078ac8 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -18,7 +18,6 @@ static uint cpas_dump; module_param(cpas_dump, uint, 0644); - void cam_cpas_dump_axi_vote_info( const struct cam_cpas_client *cpas_client, const char *identifier, @@ -467,6 +466,51 @@ static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core, return 0; } +int cam_cpas_get_hw_fuse(struct platform_device *pdev, + struct cam_cpas_private_soc *soc_private) +{ + struct device_node *of_node; + void *fuse; + uint32_t fuse_addr, fuse_bit; + uint32_t fuse_val = 0, feature_bit_pos; + int count = 0, i = 0; + + memset(&soc_private->fuse_info, 0, sizeof(soc_private->fuse_info)); + + of_node = pdev->dev.of_node; + count = of_property_count_u32_elems(of_node, "cam_hw_fuse"); + if (count <= 0) { + CAM_INFO(CAM_CPAS, "no or invalid fuse enrties %d", count); + return 0; + } else if (count%3 != 0) { + CAM_INFO(CAM_CPAS, "fuse entries should be multiple of 3 %d", + count); + return -EINVAL; + } + + for (i = 0; i < count; i = i + 3) { + of_property_read_u32_index(of_node, "cam_hw_fuse", i, + &feature_bit_pos); + of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1, + &fuse_addr); + of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2, + &fuse_bit); + CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d", + feature_bit_pos, fuse_addr, fuse_bit); + fuse = ioremap(fuse_addr, 4); + if (fuse) { + fuse_val = cam_io_r(fuse); + soc_private->fuse_info.fuse_val[i].fuse_id = fuse_addr; + soc_private->fuse_info.fuse_val[i].fuse_val = fuse_val; + } + CAM_INFO(CAM_CPAS, "fuse_addr 0x%x, fuse_val %x", + fuse_addr, fuse_val); + soc_private->fuse_info.num_fuses++; + iounmap(fuse); + } + + return 0; +} int cam_cpas_get_hw_features(struct platform_device *pdev, struct cam_cpas_private_soc *soc_private) @@ -532,6 +576,7 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, } cam_cpas_get_hw_features(pdev, soc_private); + cam_cpas_get_hw_fuse(pdev, soc_private); soc_private->camnoc_axi_min_ib_bw = 0; rc = of_property_read_u64(of_node, diff --git a/drivers/cam_cpas/cam_cpas_soc.h b/drivers/cam_cpas/cam_cpas_soc.h index 45a045ef6f..71d11bdfc3 100644 --- a/drivers/cam_cpas/cam_cpas_soc.h +++ b/drivers/cam_cpas/cam_cpas_soc.h @@ -91,6 +91,7 @@ struct cam_cpas_tree_node { * camnoc axi clock * @camnoc_axi_min_ib_bw: Min camnoc BW which varies based on target * @feature_mask: feature mask value for hw supported features + * @fuse_info: fuse information * */ struct cam_cpas_private_soc { @@ -109,6 +110,7 @@ struct cam_cpas_private_soc { uint32_t camnoc_axi_clk_bw_margin; uint64_t camnoc_axi_min_ib_bw; uint32_t feature_mask; + struct cam_cpas_fuse_info fuse_info; }; void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private); diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 1b08b427dd..1c248060bb 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -575,15 +575,17 @@ int cam_cpas_reg_read( * @camera_version : Camera platform version * @cpas_version : Camera cpas version * @cam_caps : Camera capability + * @cam_fuse_info : Camera fuse info * * @return 0 on success. * */ int cam_cpas_get_hw_info( - uint32_t *camera_family, - struct cam_hw_version *camera_version, - struct cam_hw_version *cpas_version, - uint32_t *cam_caps); + uint32_t *camera_family, + struct cam_hw_version *camera_version, + struct cam_hw_version *cpas_version, + uint32_t *cam_caps, + struct cam_cpas_fuse_info *cam_fuse_info); /** * cam_cpas_get_cpas_hw_version() 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 9ca55f30db..1cb3ed520c 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 @@ -6093,7 +6093,8 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl, mutex_init(&icp_hw_mgr.ctx_data[i].ctx_mutex); rc = cam_cpas_get_hw_info(&query.camera_family, - &query.camera_version, &query.cpas_version, &cam_caps); + &query.camera_version, &query.cpas_version, + &cam_caps, NULL); if (rc) { CAM_ERR(CAM_ICP, "failed to get hw info rc=%d", rc); goto destroy_mutex; diff --git a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c index d7eee64a37..7b06185260 100644 --- a/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c +++ b/drivers/cam_icp/icp_hw/ipe_hw/ipe_dev.c @@ -77,7 +77,8 @@ static int cam_ipe_component_bind(struct device *dev, "cell-index", &hw_idx); rc = cam_cpas_get_hw_info(&query.camera_family, - &query.camera_version, &query.cpas_version, &cam_caps); + &query.camera_version, &query.cpas_version, + &cam_caps, NULL); if (rc) { CAM_ERR(CAM_ICP, "failed to get hw info rc=%d", rc); return rc; diff --git a/include/uapi/camera/media/cam_cpas.h b/include/uapi/camera/media/cam_cpas.h index 71d1f131cb..b30326af26 100644 --- a/include/uapi/camera/media/cam_cpas.h +++ b/include/uapi/camera/media/cam_cpas.h @@ -61,7 +61,30 @@ #define CAM_AXI_PATH_DATA_OPE_MAX_OFFSET \ (CAM_AXI_PATH_DATA_OPE_START_OFFSET + 31) -#define CAM_AXI_PATH_DATA_ALL 256 +#define CAM_AXI_PATH_DATA_ALL 256 +#define CAM_CPAS_FUSES_MAX 32 + +/** + * struct cam_cpas_fuse_value - CPAS fuse value + * + * @fuse_id : Camera fuse identification + * @fuse_val : Camera Fuse Value + */ +struct cam_cpas_fuse_value { + __u32 fuse_id; + __u32 fuse_val; +}; + +/** + * struct cam_cpas_fuse_info - CPAS fuse info + * + * @num_fuses : Number of fuses + * @fuse_val : Array of different fuse info. + */ +struct cam_cpas_fuse_info { + __u32 num_fuses; + struct cam_cpas_fuse_value fuse_val[CAM_CPAS_FUSES_MAX]; +}; /** * struct cam_cpas_query_cap - CPAS query device capability payload @@ -79,6 +102,24 @@ struct cam_cpas_query_cap { struct cam_hw_version cpas_version; }; +/** + * struct cam_cpas_query_cap - CPAS query device capability payload + * + * @camera_family : Camera family type + * @reserved : Reserved field for alignment + * @camera_version : Camera platform version + * @cpas_version : Camera CPAS version within camera platform + * @fuse_info : Camera fuse info + * + */ +struct cam_cpas_query_cap_v2 { + __u32 camera_family; + __u32 reserved; + struct cam_hw_version camera_version; + struct cam_hw_version cpas_version; + struct cam_cpas_fuse_info fuse_info; +}; + /** * struct cam_axi_per_path_bw_vote - Per path bandwidth vote information * diff --git a/include/uapi/camera/media/cam_defs.h b/include/uapi/camera/media/cam_defs.h index 4c132a8a2f..d6e2a7fb15 100644 --- a/include/uapi/camera/media/cam_defs.h +++ b/include/uapi/camera/media/cam_defs.h @@ -21,7 +21,8 @@ #define CAM_RELEASE_DEV (CAM_COMMON_OPCODE_BASE + 0x6) #define CAM_SD_SHUTDOWN (CAM_COMMON_OPCODE_BASE + 0x7) #define CAM_FLUSH_REQ (CAM_COMMON_OPCODE_BASE + 0x8) -#define CAM_COMMON_OPCODE_MAX (CAM_COMMON_OPCODE_BASE + 0x9) +#define CAM_QUERY_CAP_V2 (CAM_COMMON_OPCODE_BASE + 0x9) +#define CAM_COMMON_OPCODE_MAX (CAM_COMMON_OPCODE_BASE + 0xa) #define CAM_COMMON_OPCODE_BASE_v2 0x150 #define CAM_ACQUIRE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x1)