diff --git a/drivers/cam_cpas/cam_cpas_hw.c b/drivers/cam_cpas/cam_cpas_hw.c index 6661944105..0c029d39a2 100644 --- a/drivers/cam_cpas/cam_cpas_hw.c +++ b/drivers/cam_cpas/cam_cpas_hw.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -983,7 +983,8 @@ static int cam_cpas_apply_smart_qos( struct cam_cpas_tree_node *niu_node; struct cam_camnoc_info *camnoc_info; uint8_t i; - int32_t reg_indx; + int32_t reg_indx, cam_qos_cnt = 0, ret = 0; + struct qcom_scm_camera_qos scm_buf[QCOM_SCM_CAMERA_MAX_QOS_CNT] = {0}; if (cpas_core->smart_qos_dump) { CAM_INFO(CAM_PERF, "Printing SmartQos values before update"); @@ -998,20 +999,44 @@ static int cam_cpas_apply_smart_qos( niu_node = soc_private->smart_qos_info->rt_wr_niu_node[i]; if (niu_node->curr_priority_high != niu_node->applied_priority_high) { - cam_io_w_mb(niu_node->curr_priority_high, - soc_info->reg_map[reg_indx].mem_base + - niu_node->pri_lut_high_offset); + if (!soc_private->enable_secure_qos_update) { + cam_io_w_mb(niu_node->curr_priority_high, + soc_info->reg_map[reg_indx].mem_base + + niu_node->pri_lut_high_offset); + } else { + scm_buf[cam_qos_cnt].offset = niu_node->pri_lut_high_offset; + scm_buf[cam_qos_cnt].val = niu_node->curr_priority_high; + cam_qos_cnt++; + } niu_node->applied_priority_high = niu_node->curr_priority_high; } if (niu_node->curr_priority_low != niu_node->applied_priority_low) { - cam_io_w_mb(niu_node->curr_priority_low, - soc_info->reg_map[reg_indx].mem_base + - niu_node->pri_lut_low_offset); + if (!soc_private->enable_secure_qos_update) { + cam_io_w_mb(niu_node->curr_priority_low, + soc_info->reg_map[reg_indx].mem_base + + niu_node->pri_lut_low_offset); + } else { + scm_buf[cam_qos_cnt].offset = niu_node->pri_lut_low_offset; + scm_buf[cam_qos_cnt].val = niu_node->curr_priority_low; + cam_qos_cnt++; + } niu_node->applied_priority_low = niu_node->curr_priority_low; } + + if (soc_private->enable_secure_qos_update && cam_qos_cnt) { + CAM_DBG(CAM_PERF, "Updating secure camera smartOos count: %d", cam_qos_cnt); + ret = cam_update_camnoc_qos_settings(CAM_QOS_UPDATE_TYPE_SMART, + cam_qos_cnt, scm_buf); + if (ret) { + CAM_ERR(CAM_PERF, "Secure camera smartOos update failed:%d", ret); + return ret; + } + CAM_DBG(CAM_PERF, "Updated secure camera smartOos"); + cam_qos_cnt = 0; + } } if (cpas_core->smart_qos_dump) { diff --git a/drivers/cam_cpas/cam_cpas_soc.c b/drivers/cam_cpas/cam_cpas_soc.c index 23fd1b527b..97061e76f8 100644 --- a/drivers/cam_cpas/cam_cpas_soc.c +++ b/drivers/cam_cpas/cam_cpas_soc.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -1455,6 +1455,9 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw, soc_private->num_vdd_ahb_mapping = count; } + soc_private->enable_secure_qos_update = of_property_read_bool(of_node, + "enable-secure-qos-update"); + soc_private->enable_smart_qos = of_property_read_bool(of_node, "enable-smart-qos"); diff --git a/drivers/cam_cpas/cam_cpas_soc.h b/drivers/cam_cpas/cam_cpas_soc.h index c6f1d8b420..0e39a62dad 100644 --- a/drivers/cam_cpas/cam_cpas_soc.h +++ b/drivers/cam_cpas/cam_cpas_soc.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_CPAS_SOC_H_ @@ -268,6 +268,7 @@ struct cam_cpas_sysfs_info { * @num_caches: Number of last level caches * @part_info: Camera Hw subpart info * @llcc_info: Cache info + * @enable_secure_qos_update: whether to program QoS securely on current chipset * @enable_smart_qos: Whether to enable Smart QoS mechanism on current chipset * @enable_cam_ddr_drv: Whether to enable Camera DDR DRV on current chipset * @enable_cam_clk_drv: Whether to enable Camera Clk DRV on current chipset @@ -303,6 +304,7 @@ struct cam_cpas_private_soc { bool enable_smart_qos; bool enable_cam_ddr_drv; bool enable_cam_clk_drv; + bool enable_secure_qos_update; struct cam_cpas_smart_qos_info *smart_qos_info; int32_t icp_clk_index; struct cam_cpas_domain_id_info domain_id_info; diff --git a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c index 3e6b855659..8b3d0b46b9 100644 --- a/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -1040,59 +1040,72 @@ static int cam_cpastop_print_poweron_settings(struct cam_hw_info *cpas_hw) static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw) { - int i, j; + int i, j, rc = 0; struct cam_cpas_hw_errata_wa_list *errata_wa_list; struct cam_cpas_hw_errata_wa *errata_wa; struct cam_cpas *cpas_core = cpas_hw->core_info; + struct cam_cpas_private_soc *soc_private = + (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; bool errata_enabled = false; for (i = 0; i < cpas_core->num_valid_camnoc; i++) cam_cpastop_reset_irq(0x0, cpas_hw, i); - for (i = 0; i < cpas_core->num_valid_camnoc; i++) { - CAM_DBG(CAM_CPAS, "QOS settings for %s :", - camnoc_info[i]->camnoc_name); - for (j = 0; j < camnoc_info[i]->specific_size; j++) { - if (camnoc_info[i]->specific[j].enable) { - CAM_DBG(CAM_CPAS, - "Updating QoS settings port: %d prot name: %s", - camnoc_info[i]->specific[j].port_type, - camnoc_info[i]->specific[j].port_name); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].priority_lut_low); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].priority_lut_high); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].urgency); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].danger_lut); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].safe_lut); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].ubwc_ctl); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].flag_out_set0_low); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].dynattr_mainctl); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].qosgen_mainctl); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].qosgen_shaping_low); - cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, - &camnoc_info[i]->specific[j].qosgen_shaping_high); - } - } + if (!soc_private->enable_secure_qos_update) { + for (i = 0; i < cpas_core->num_valid_camnoc; i++) { + CAM_DBG(CAM_CPAS, "QOS settings for %s :", + camnoc_info[i]->camnoc_name); + for (j = 0; j < camnoc_info[i]->specific_size; j++) { + if (camnoc_info[i]->specific[j].enable) { + CAM_DBG(CAM_CPAS, + "Updating QoS settings port: %d prot name: %s", + camnoc_info[i]->specific[j].port_type, + camnoc_info[i]->specific[j].port_name); - if (!errata_enabled) { - errata_wa_list = camnoc_info[i]->errata_wa_list; - if (errata_wa_list) { - errata_wa = &errata_wa_list->tcsr_camera_hf_sf_ares_glitch; - if (errata_wa->enable) { - cam_cpastop_scm_write(errata_wa); - errata_enabled = true; + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].priority_lut_low); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].priority_lut_high); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].urgency); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].danger_lut); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].safe_lut); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].ubwc_ctl); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].flag_out_set0_low); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].dynattr_mainctl); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].qosgen_mainctl); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].qosgen_shaping_low); + cam_cpas_util_reg_update(cpas_hw, camnoc_info[i]->reg_base, + &camnoc_info[i]->specific[j].qosgen_shaping_high); + } + } + + if (!errata_enabled) { + errata_wa_list = camnoc_info[i]->errata_wa_list; + if (errata_wa_list) { + errata_wa = &errata_wa_list->tcsr_camera_hf_sf_ares_glitch; + if (errata_wa->enable) { + cam_cpastop_scm_write(errata_wa); + errata_enabled = true; + } } } } + } else { + CAM_DBG(CAM_CPAS, "Updating secure camera static QoS settings"); + rc = cam_update_camnoc_qos_settings(CAM_QOS_UPDATE_TYPE_STATIC, 0, NULL); + if (rc) { + CAM_ERR(CAM_CPAS, "Secure camera static OoS update failed: %d", rc); + return rc; + } + CAM_DBG(CAM_CPAS, "Updated secure camera static QoS settings"); } return 0; diff --git a/drivers/cam_cpas/include/cam_cpas_api.h b/drivers/cam_cpas/include/cam_cpas_api.h index 01d9e19690..7ee1e7d911 100644 --- a/drivers/cam_cpas/include/cam_cpas_api.h +++ b/drivers/cam_cpas/include/cam_cpas_api.h @@ -32,6 +32,15 @@ #define CAM_CPAS_QOS_DEFAULT_SETTINGS_MASK 0x1 #define CAM_CPAS_QOS_CUSTOM_SETTINGS_MASK 0x2 +/** + * Secure camera QoS update id - Enum for identify QOS settings update type + */ +enum secure_camera_qos_update_type { + CAM_QOS_UPDATE_TYPE_STATIC = 0x0, + CAM_QOS_UPDATE_TYPE_SMART = 0x1, + CAM_QOS_UPDATE_TYPE_MAX, +}; + /** * enum cam_cpas_regbase_types - Enum for cpas regbase available for clients * to read/write diff --git a/drivers/cam_utils/cam_compat.c b/drivers/cam_utils/cam_compat.c index 6c0fa01d79..08b4b7cfa5 100644 --- a/drivers/cam_utils/cam_compat.c +++ b/drivers/cam_utils/cam_compat.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -441,6 +441,20 @@ int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev, } #endif +int cam_update_camnoc_qos_settings(uint32_t use_case_id, + uint32_t qos_cnt, struct qcom_scm_camera_qos *scm_buf) +{ + int rc = 0; + + rc = qcom_scm_camera_update_camnoc_qos(use_case_id, qos_cnt, scm_buf); + if (rc) { + CAM_ERR(CAM_ISP, "scm call to update QoS failed: %d", rc); + rc = -EINVAL; + } + + return rc; +} + /* Callback to compare device from match list before adding as component */ static inline int camera_component_compare_dev(struct device *dev, void *data) { diff --git a/drivers/cam_utils/cam_compat.h b/drivers/cam_utils/cam_compat.h index 6f24729bd8..aa2cedff1d 100644 --- a/drivers/cam_utils/cam_compat.h +++ b/drivers/cam_utils/cam_compat.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _CAM_COMPAT_H_ @@ -61,6 +61,8 @@ struct cam_fw_alloc_info { int cam_reserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length); void cam_unreserve_icp_fw(struct cam_fw_alloc_info *icp_fw, size_t fw_length); void cam_cpastop_scm_write(struct cam_cpas_hw_errata_wa *errata_wa); +int cam_update_camnoc_qos_settings(uint32_t use_case_id, + uint32_t num_arg, struct qcom_scm_camera_qos *scm_buf); int cam_ife_notify_safe_lut_scm(bool safe_trigger); int camera_component_match_add_drivers(struct device *master_dev, struct component_match **match_list);