Loading drivers/cam_cpas/cam_cpas_hw.c +65 −4 Original line number Diff line number Diff line Loading @@ -134,7 +134,7 @@ static int cam_cpas_util_vote_bus_client_level( static int cam_cpas_util_vote_bus_client_bw( struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib, bool camnoc_bw) bool camnoc_bw, uint64_t *applied_ab, uint64_t *applied_ib) { int rc = 0; uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW; Loading Loading @@ -193,6 +193,11 @@ static int cam_cpas_util_vote_bus_client_bw( goto unlock_client; } if (applied_ab) *applied_ab = ab; if (applied_ib) *applied_ib = ib; unlock_client: mutex_unlock(&bus_client->lock); end: Loading Loading @@ -311,6 +316,7 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw, int rc, i = 0; struct cam_cpas *cpas_core = (struct cam_cpas *)cpas_hw->core_info; uint64_t ab_bw, ib_bw; uint64_t applied_ab_bw = 0, applied_ib_bw = 0; rc = cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client, (enable == true) ? CAM_SVS_VOTE : CAM_SUSPEND_VOTE); Loading @@ -331,13 +337,15 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw, for (i = 0; i < cpas_core->num_axi_ports; i++) { rc = cam_cpas_util_vote_bus_client_bw( &cpas_core->axi_port[i].bus_client, ab_bw, ib_bw, false); ab_bw, ib_bw, false, &applied_ab_bw, &applied_ib_bw); if (rc) { CAM_ERR(CAM_CPAS, "Failed in mnoc vote, enable=%d, rc=%d", enable, rc); goto remove_ahb_vote; } cpas_core->axi_port[i].applied_ab_bw = applied_ab_bw; cpas_core->axi_port[i].applied_ib_bw = applied_ib_bw; } return 0; Loading Loading @@ -518,6 +526,8 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( CAM_ERR(CAM_CPAS, "Failed in setting camnoc axi clk %llu %d %d", required_camnoc_bw, clk_rate, rc); cpas_core->applied_camnoc_axi_rate = clk_rate; } } Loading Loading @@ -699,6 +709,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( int rc = 0; struct cam_cpas_axi_port *camnoc_axi_port = NULL; uint64_t camnoc_bw; uint64_t applied_ab = 0, applied_ib = 0; if (soc_private->control_camnoc_axi_clk) { rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw); Loading Loading @@ -739,7 +750,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( rc = cam_cpas_util_vote_bus_client_bw( &camnoc_axi_port->bus_client, 0, camnoc_bw, true); 0, camnoc_bw, true, &applied_ab, &applied_ib); CAM_DBG(CAM_CPAS, "camnoc vote camnoc_bw[%llu] rc=%d %s", Loading @@ -750,6 +761,8 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( camnoc_bw, rc); break; } camnoc_axi_port->applied_ab_bw = applied_ab; camnoc_axi_port->applied_ib_bw = applied_ib; } return rc; } Loading @@ -772,6 +785,7 @@ static int cam_cpas_util_apply_client_axi_vote( curr_camnoc_old = 0, curr_mnoc_ab_old = 0, curr_mnoc_ib_old = 0, par_camnoc_old = 0, par_mnoc_ab_old = 0, par_mnoc_ib_old = 0; int rc = 0, i = 0; uint64_t applied_ab = 0, applied_ib = 0; mutex_lock(&cpas_core->tree_lock); if (!cpas_client->tree_node_valid) { Loading Loading @@ -947,13 +961,16 @@ static int cam_cpas_util_apply_client_axi_vote( rc = cam_cpas_util_vote_bus_client_bw( &mnoc_axi_port->bus_client, mnoc_ab_bw, mnoc_ib_bw, false); mnoc_ab_bw, mnoc_ib_bw, false, &applied_ab, &applied_ib); if (rc) { CAM_ERR(CAM_CPAS, "Failed in mnoc vote ab[%llu] ib[%llu] rc=%d", mnoc_ab_bw, mnoc_ib_bw, rc); goto unlock_tree; } mnoc_axi_port->applied_ab_bw = applied_ab; mnoc_axi_port->applied_ib_bw = applied_ib; } rc = cam_cpas_camnoc_set_vote_axi_clk_rate( cpas_hw, camnoc_axi_port_updated); Loading Loading @@ -1703,6 +1720,46 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv, return 0; } static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw) { struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; struct cam_cpas_private_soc *soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; int rc = 0; uint32_t i; for (i = 0; i < cpas_core->num_axi_ports; i++) { CAM_INFO(CAM_CPAS, "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]", cpas_core->axi_port[i].axi_port_name, cpas_core->axi_port[i].ab_bw, cpas_core->axi_port[i].ib_bw, cpas_core->axi_port[i].additional_bw, cpas_core->axi_port[i].applied_ab_bw, cpas_core->axi_port[i].applied_ib_bw); } if (soc_private->control_camnoc_axi_clk) { CAM_INFO(CAM_CPAS, "applied camnoc axi clk[%lld]", cpas_core->applied_camnoc_axi_rate); } else { for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) { CAM_INFO(CAM_CPAS, "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]", cpas_core->camnoc_axi_port[i].axi_port_name, cpas_core->camnoc_axi_port[i].ab_bw, cpas_core->camnoc_axi_port[i].ib_bw, cpas_core->camnoc_axi_port[i].additional_bw, cpas_core->camnoc_axi_port[i].applied_ab_bw, cpas_core->camnoc_axi_port[i].applied_ib_bw); } } CAM_INFO(CAM_CPAS, "ahb client curr vote level[%d]", cpas_core->ahb_bus_client.curr_vote_level); return rc; } static int cam_cpas_hw_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) Loading Loading @@ -1806,6 +1863,10 @@ static int cam_cpas_hw_process_cmd(void *hw_priv, cmd_axi_vote->client_handle, cmd_axi_vote->axi_vote); break; } case CAM_CPAS_HW_CMD_LOG_VOTE: { rc = cam_cpas_log_vote(hw_priv); break; } default: CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type); break; Loading drivers/cam_cpas/cam_cpas_hw.h +6 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,8 @@ struct cam_cpas_bus_client { * @ib_bw: IB bw value for this port * @camnoc_bw: CAMNOC bw value for this port * @additional_bw: Additional bandwidth to cover non-hw cpas clients * @applied_ab_bw: applied ab bw for this port * @applied_ib_bw: applied ib bw for this port */ struct cam_cpas_axi_port { const char *axi_port_name; Loading @@ -154,6 +156,8 @@ struct cam_cpas_axi_port { uint64_t ib_bw; uint64_t camnoc_bw; uint64_t additional_bw; uint64_t applied_ab_bw; uint64_t applied_ib_bw; }; /** Loading @@ -178,6 +182,7 @@ struct cam_cpas_axi_port { * @irq_count_wq: wait variable to ensure all irq's are handled * @dentry: debugfs file entry * @ahb_bus_scaling_disable: ahb scaling based on src clk corner for bus * @applied_camnoc_axi_rate: applied camnoc axi clock rate */ struct cam_cpas { struct cam_cpas_hw_caps hw_caps; Loading @@ -199,6 +204,7 @@ struct cam_cpas { wait_queue_head_t irq_count_wq; struct dentry *dentry; bool ahb_bus_scaling_disable; uint64_t applied_camnoc_axi_rate; }; int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); Loading drivers/cam_cpas/cam_cpas_hw_intf.h +2 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_HW_INTF_H_ Loading Loading @@ -38,6 +38,7 @@ enum cam_cpas_hw_cmd_process { CAM_CPAS_HW_CMD_REG_READ, CAM_CPAS_HW_CMD_AHB_VOTE, CAM_CPAS_HW_CMD_AXI_VOTE, CAM_CPAS_HW_CMD_LOG_VOTE, CAM_CPAS_HW_CMD_INVALID, }; Loading drivers/cam_cpas/cam_cpas_intf.c +24 −0 Original line number Diff line number Diff line Loading @@ -405,6 +405,30 @@ int cam_cpas_start(uint32_t client_handle, } EXPORT_SYMBOL(cam_cpas_start); void cam_cpas_log_votes(void) { uint32_t dummy_args; int rc; if (!CAM_CPAS_INTF_INITIALIZED()) { CAM_ERR(CAM_CPAS, "cpas intf not initialized"); return; } if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( g_cpas_intf->hw_intf->hw_priv, CAM_CPAS_HW_CMD_LOG_VOTE, &dummy_args, sizeof(dummy_args)); if (rc) CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); } else { CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); } } EXPORT_SYMBOL(cam_cpas_log_votes); int cam_cpas_unregister_client(uint32_t client_handle) { int rc; Loading drivers/cam_cpas/include/cam_cpas_api.h +10 −0 Original line number Diff line number Diff line Loading @@ -622,5 +622,15 @@ const char *cam_cpas_axi_util_path_type_to_string( const char *cam_cpas_axi_util_trans_type_to_string( uint32_t path_data_type); /** * cam_cpas_log_votes() * * @brief: API to print the all bw votes of axi client. It also print the * applied camnoc axi clock vote value and ahb vote value * * @return 0 on success. * */ void cam_cpas_log_votes(void); #endif /* _CAM_CPAS_API_H_ */ Loading
drivers/cam_cpas/cam_cpas_hw.c +65 −4 Original line number Diff line number Diff line Loading @@ -134,7 +134,7 @@ static int cam_cpas_util_vote_bus_client_level( static int cam_cpas_util_vote_bus_client_bw( struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib, bool camnoc_bw) bool camnoc_bw, uint64_t *applied_ab, uint64_t *applied_ib) { int rc = 0; uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW; Loading Loading @@ -193,6 +193,11 @@ static int cam_cpas_util_vote_bus_client_bw( goto unlock_client; } if (applied_ab) *applied_ab = ab; if (applied_ib) *applied_ib = ib; unlock_client: mutex_unlock(&bus_client->lock); end: Loading Loading @@ -311,6 +316,7 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw, int rc, i = 0; struct cam_cpas *cpas_core = (struct cam_cpas *)cpas_hw->core_info; uint64_t ab_bw, ib_bw; uint64_t applied_ab_bw = 0, applied_ib_bw = 0; rc = cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client, (enable == true) ? CAM_SVS_VOTE : CAM_SUSPEND_VOTE); Loading @@ -331,13 +337,15 @@ static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw, for (i = 0; i < cpas_core->num_axi_ports; i++) { rc = cam_cpas_util_vote_bus_client_bw( &cpas_core->axi_port[i].bus_client, ab_bw, ib_bw, false); ab_bw, ib_bw, false, &applied_ab_bw, &applied_ib_bw); if (rc) { CAM_ERR(CAM_CPAS, "Failed in mnoc vote, enable=%d, rc=%d", enable, rc); goto remove_ahb_vote; } cpas_core->axi_port[i].applied_ab_bw = applied_ab_bw; cpas_core->axi_port[i].applied_ib_bw = applied_ib_bw; } return 0; Loading Loading @@ -518,6 +526,8 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( CAM_ERR(CAM_CPAS, "Failed in setting camnoc axi clk %llu %d %d", required_camnoc_bw, clk_rate, rc); cpas_core->applied_camnoc_axi_rate = clk_rate; } } Loading Loading @@ -699,6 +709,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( int rc = 0; struct cam_cpas_axi_port *camnoc_axi_port = NULL; uint64_t camnoc_bw; uint64_t applied_ab = 0, applied_ib = 0; if (soc_private->control_camnoc_axi_clk) { rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw); Loading Loading @@ -739,7 +750,7 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( rc = cam_cpas_util_vote_bus_client_bw( &camnoc_axi_port->bus_client, 0, camnoc_bw, true); 0, camnoc_bw, true, &applied_ab, &applied_ib); CAM_DBG(CAM_CPAS, "camnoc vote camnoc_bw[%llu] rc=%d %s", Loading @@ -750,6 +761,8 @@ static int cam_cpas_camnoc_set_vote_axi_clk_rate( camnoc_bw, rc); break; } camnoc_axi_port->applied_ab_bw = applied_ab; camnoc_axi_port->applied_ib_bw = applied_ib; } return rc; } Loading @@ -772,6 +785,7 @@ static int cam_cpas_util_apply_client_axi_vote( curr_camnoc_old = 0, curr_mnoc_ab_old = 0, curr_mnoc_ib_old = 0, par_camnoc_old = 0, par_mnoc_ab_old = 0, par_mnoc_ib_old = 0; int rc = 0, i = 0; uint64_t applied_ab = 0, applied_ib = 0; mutex_lock(&cpas_core->tree_lock); if (!cpas_client->tree_node_valid) { Loading Loading @@ -947,13 +961,16 @@ static int cam_cpas_util_apply_client_axi_vote( rc = cam_cpas_util_vote_bus_client_bw( &mnoc_axi_port->bus_client, mnoc_ab_bw, mnoc_ib_bw, false); mnoc_ab_bw, mnoc_ib_bw, false, &applied_ab, &applied_ib); if (rc) { CAM_ERR(CAM_CPAS, "Failed in mnoc vote ab[%llu] ib[%llu] rc=%d", mnoc_ab_bw, mnoc_ib_bw, rc); goto unlock_tree; } mnoc_axi_port->applied_ab_bw = applied_ab; mnoc_axi_port->applied_ib_bw = applied_ib; } rc = cam_cpas_camnoc_set_vote_axi_clk_rate( cpas_hw, camnoc_axi_port_updated); Loading Loading @@ -1703,6 +1720,46 @@ static int cam_cpas_hw_get_hw_info(void *hw_priv, return 0; } static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw) { struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; struct cam_cpas_private_soc *soc_private = (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private; int rc = 0; uint32_t i; for (i = 0; i < cpas_core->num_axi_ports; i++) { CAM_INFO(CAM_CPAS, "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]", cpas_core->axi_port[i].axi_port_name, cpas_core->axi_port[i].ab_bw, cpas_core->axi_port[i].ib_bw, cpas_core->axi_port[i].additional_bw, cpas_core->axi_port[i].applied_ab_bw, cpas_core->axi_port[i].applied_ib_bw); } if (soc_private->control_camnoc_axi_clk) { CAM_INFO(CAM_CPAS, "applied camnoc axi clk[%lld]", cpas_core->applied_camnoc_axi_rate); } else { for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) { CAM_INFO(CAM_CPAS, "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]", cpas_core->camnoc_axi_port[i].axi_port_name, cpas_core->camnoc_axi_port[i].ab_bw, cpas_core->camnoc_axi_port[i].ib_bw, cpas_core->camnoc_axi_port[i].additional_bw, cpas_core->camnoc_axi_port[i].applied_ab_bw, cpas_core->camnoc_axi_port[i].applied_ib_bw); } } CAM_INFO(CAM_CPAS, "ahb client curr vote level[%d]", cpas_core->ahb_bus_client.curr_vote_level); return rc; } static int cam_cpas_hw_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) Loading Loading @@ -1806,6 +1863,10 @@ static int cam_cpas_hw_process_cmd(void *hw_priv, cmd_axi_vote->client_handle, cmd_axi_vote->axi_vote); break; } case CAM_CPAS_HW_CMD_LOG_VOTE: { rc = cam_cpas_log_vote(hw_priv); break; } default: CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type); break; Loading
drivers/cam_cpas/cam_cpas_hw.h +6 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,8 @@ struct cam_cpas_bus_client { * @ib_bw: IB bw value for this port * @camnoc_bw: CAMNOC bw value for this port * @additional_bw: Additional bandwidth to cover non-hw cpas clients * @applied_ab_bw: applied ab bw for this port * @applied_ib_bw: applied ib bw for this port */ struct cam_cpas_axi_port { const char *axi_port_name; Loading @@ -154,6 +156,8 @@ struct cam_cpas_axi_port { uint64_t ib_bw; uint64_t camnoc_bw; uint64_t additional_bw; uint64_t applied_ab_bw; uint64_t applied_ib_bw; }; /** Loading @@ -178,6 +182,7 @@ struct cam_cpas_axi_port { * @irq_count_wq: wait variable to ensure all irq's are handled * @dentry: debugfs file entry * @ahb_bus_scaling_disable: ahb scaling based on src clk corner for bus * @applied_camnoc_axi_rate: applied camnoc axi clock rate */ struct cam_cpas { struct cam_cpas_hw_caps hw_caps; Loading @@ -199,6 +204,7 @@ struct cam_cpas { wait_queue_head_t irq_count_wq; struct dentry *dentry; bool ahb_bus_scaling_disable; uint64_t applied_camnoc_axi_rate; }; int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops); Loading
drivers/cam_cpas/cam_cpas_hw_intf.h +2 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_CPAS_HW_INTF_H_ Loading Loading @@ -38,6 +38,7 @@ enum cam_cpas_hw_cmd_process { CAM_CPAS_HW_CMD_REG_READ, CAM_CPAS_HW_CMD_AHB_VOTE, CAM_CPAS_HW_CMD_AXI_VOTE, CAM_CPAS_HW_CMD_LOG_VOTE, CAM_CPAS_HW_CMD_INVALID, }; Loading
drivers/cam_cpas/cam_cpas_intf.c +24 −0 Original line number Diff line number Diff line Loading @@ -405,6 +405,30 @@ int cam_cpas_start(uint32_t client_handle, } EXPORT_SYMBOL(cam_cpas_start); void cam_cpas_log_votes(void) { uint32_t dummy_args; int rc; if (!CAM_CPAS_INTF_INITIALIZED()) { CAM_ERR(CAM_CPAS, "cpas intf not initialized"); return; } if (g_cpas_intf->hw_intf->hw_ops.process_cmd) { rc = g_cpas_intf->hw_intf->hw_ops.process_cmd( g_cpas_intf->hw_intf->hw_priv, CAM_CPAS_HW_CMD_LOG_VOTE, &dummy_args, sizeof(dummy_args)); if (rc) CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc); } else { CAM_ERR(CAM_CPAS, "Invalid process_cmd ops"); } } EXPORT_SYMBOL(cam_cpas_log_votes); int cam_cpas_unregister_client(uint32_t client_handle) { int rc; Loading
drivers/cam_cpas/include/cam_cpas_api.h +10 −0 Original line number Diff line number Diff line Loading @@ -622,5 +622,15 @@ const char *cam_cpas_axi_util_path_type_to_string( const char *cam_cpas_axi_util_trans_type_to_string( uint32_t path_data_type); /** * cam_cpas_log_votes() * * @brief: API to print the all bw votes of axi client. It also print the * applied camnoc axi clock vote value and ahb vote value * * @return 0 on success. * */ void cam_cpas_log_votes(void); #endif /* _CAM_CPAS_API_H_ */