Loading drivers/cam_cpas/cam_cpas_hw.c +66 −5 Original line number Diff line number Diff line Loading @@ -83,7 +83,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) { struct msm_bus_paths *path; struct msm_bus_scale_pdata *pdata; Loading Loading @@ -146,6 +146,10 @@ static int cam_cpas_util_vote_bus_client_bw( CAM_DBG(CAM_CPAS, "Bus client=[%d][%s] :ab[%llu] ib[%llu], index[%d]", bus_client->client_id, bus_client->name, ab, ib, idx); msm_bus_scale_client_update_request(bus_client->client_id, idx); if (applied_ab) *applied_ab = ab; if (applied_ib) *applied_ib = ib; return 0; } Loading Loading @@ -221,7 +225,8 @@ static int cam_cpas_util_unregister_bus_client( return -EINVAL; if (bus_client->dyn_vote) cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false); cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false, NULL, NULL); else cam_cpas_util_vote_bus_client_level(bus_client, 0); Loading Loading @@ -309,6 +314,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 @@ -329,13 +335,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 @@ -501,6 +509,8 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( CAM_ERR(CAM_CPAS, "Failed in setting camnoc axi clk %llu %lld %d", required_camnoc_bw, clk_rate, rc); cpas_core->applied_camnoc_axi_rate = clk_rate; } } Loading Loading @@ -689,6 +699,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 @@ -729,7 +740,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 @@ -740,6 +751,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 @@ -762,6 +775,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 @@ -923,13 +937,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 @@ -1676,6 +1693,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 @@ -1779,6 +1836,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 @@ -155,6 +155,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 @@ -165,6 +167,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 @@ -189,6 +193,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 @@ -210,6 +215,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-2018, 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 +25 −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. */ #include <linux/of.h> Loading Loading @@ -392,6 +392,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 @@ -624,5 +624,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 +66 −5 Original line number Diff line number Diff line Loading @@ -83,7 +83,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) { struct msm_bus_paths *path; struct msm_bus_scale_pdata *pdata; Loading Loading @@ -146,6 +146,10 @@ static int cam_cpas_util_vote_bus_client_bw( CAM_DBG(CAM_CPAS, "Bus client=[%d][%s] :ab[%llu] ib[%llu], index[%d]", bus_client->client_id, bus_client->name, ab, ib, idx); msm_bus_scale_client_update_request(bus_client->client_id, idx); if (applied_ab) *applied_ab = ab; if (applied_ib) *applied_ib = ib; return 0; } Loading Loading @@ -221,7 +225,8 @@ static int cam_cpas_util_unregister_bus_client( return -EINVAL; if (bus_client->dyn_vote) cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false); cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false, NULL, NULL); else cam_cpas_util_vote_bus_client_level(bus_client, 0); Loading Loading @@ -309,6 +314,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 @@ -329,13 +335,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 @@ -501,6 +509,8 @@ static int cam_cpas_util_set_camnoc_axi_clk_rate( CAM_ERR(CAM_CPAS, "Failed in setting camnoc axi clk %llu %lld %d", required_camnoc_bw, clk_rate, rc); cpas_core->applied_camnoc_axi_rate = clk_rate; } } Loading Loading @@ -689,6 +699,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 @@ -729,7 +740,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 @@ -740,6 +751,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 @@ -762,6 +775,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 @@ -923,13 +937,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 @@ -1676,6 +1693,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 @@ -1779,6 +1836,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 @@ -155,6 +155,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 @@ -165,6 +167,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 @@ -189,6 +193,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 @@ -210,6 +215,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-2018, 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 +25 −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. */ #include <linux/of.h> Loading Loading @@ -392,6 +392,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 @@ -624,5 +624,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_ */