diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 575b537251c0..844f208fa639 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -4749,6 +4749,7 @@ static unsigned int ipa3_get_bus_vote(void) void ipa3_enable_clks(void) { int idx; + int i; if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) { IPAERR("not supported in this mode\n"); @@ -4757,12 +4758,16 @@ void ipa3_enable_clks(void) IPADBG("enabling IPA clocks and bus voting\n"); - /* TODO: ICC migration change pending */ idx = ipa3_get_bus_vote(); - if (icc_set_bw( - ipa3_ctx->ctrl->pcie_path, - 0, 0)) - WARN(1, "bus scaling failed"); + + for (i = 0; i < ipa3_ctx->icc_num_paths; i++) { + if (ipa3_ctx->ctrl->icc_path[i] && + icc_set_bw( + ipa3_ctx->ctrl->icc_path[i], + ipa3_ctx->icc_clk[idx][i][IPA_ICC_AB], + ipa3_ctx->icc_clk[idx][i][IPA_ICC_IB])) + WARN(1, "path %d bus scaling failed", i); + } ipa3_ctx->ctrl->ipa3_enable_clks(); atomic_set(&ipa3_ctx->ipa_clk_vote, 1); } @@ -4788,6 +4793,8 @@ void _ipa_disable_clks_v3_0(void) */ void ipa3_disable_clks(void) { + int i; + if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) { IPAERR("not supported in this mode\n"); return; @@ -4799,8 +4806,14 @@ void ipa3_disable_clks(void) ipa_pm_set_clock_index(0); - if (icc_set_bw(ipa3_ctx->ctrl->pcie_path, 0, 0)) - WARN(1, "bus scaling failed"); + for (i = 0; i < ipa3_ctx->icc_num_paths; i++) { + if (ipa3_ctx->ctrl->icc_path[i] && + icc_set_bw( + ipa3_ctx->ctrl->icc_path[i], + ipa3_ctx->icc_clk[IPA_ICC_NONE][i][IPA_ICC_AB], + ipa3_ctx->icc_clk[IPA_ICC_NONE][i][IPA_ICC_IB])) + WARN(1, "path %d bus off failed", i); + } atomic_set(&ipa3_ctx->ipa_clk_vote, 0); } @@ -5148,6 +5161,7 @@ void ipa3_dec_release_wakelock(void) int ipa3_set_clock_plan_from_pm(int idx) { u32 clk_rate; + int i; IPADBG_LOW("idx = %d\n", idx); @@ -5192,10 +5206,17 @@ int ipa3_set_clock_plan_from_pm(int idx) if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) > 0) { if (ipa3_clk) clk_set_rate(ipa3_clk, ipa3_ctx->curr_ipa_clk_rate); - /* TODO: ICC migration change pending */ - if (icc_set_bw(ipa3_ctx->ctrl->pcie_path, - 0, 0)) - WARN_ON(1); + idx = ipa3_get_bus_vote(); + for (i = 0; i < ipa3_ctx->icc_num_paths; i++) { + if (ipa3_ctx->ctrl->icc_path[i] && + icc_set_bw( + ipa3_ctx->ctrl->icc_path[i], + ipa3_ctx->icc_clk[idx][i][IPA_ICC_AB], + ipa3_ctx->icc_clk[idx][i][IPA_ICC_IB])) { + WARN(1, "path %d bus scaling failed", + i); + } + } } else { IPADBG_LOW("clocks are gated, not setting rate\n"); } @@ -5210,6 +5231,8 @@ int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage, { enum ipa_voltage_level needed_voltage; u32 clk_rate; + int i; + int idx; if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) { IPAERR("not supported in this mode\n"); @@ -5275,10 +5298,15 @@ int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage, if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) > 0) { if (ipa3_clk) clk_set_rate(ipa3_clk, ipa3_ctx->curr_ipa_clk_rate); - /* TODO: ICC migration change pending */ - if (icc_set_bw(ipa3_ctx->ctrl->pcie_path, - 0, 0)) - WARN_ON(1); + idx = ipa3_get_bus_vote(); + for (i = 0; i < ipa3_ctx->icc_num_paths; i++) { + if (ipa3_ctx->ctrl->icc_path[i] && + icc_set_bw( + ipa3_ctx->ctrl->icc_path[i], + ipa3_ctx->icc_clk[idx][i][IPA_ICC_AB], + ipa3_ctx->icc_clk[idx][i][IPA_ICC_IB])) + WARN(1, "path %d bus scaling failed", i); + } } else { IPADBG_LOW("clocks are gated, not setting rate\n"); } @@ -6539,6 +6567,18 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, ipa3_ctx->aggregation_byte_limit = 1; ipa3_ctx->aggregation_time_limit = 0; + /* configure interconnect parameters */ + ipa3_ctx->icc_num_cases = resource_p->icc_num_cases; + ipa3_ctx->icc_num_paths = resource_p->icc_num_paths; + for (i = 0; i < ipa3_ctx->icc_num_cases; i++) { + for (j = 0; j < ipa3_ctx->icc_num_paths; j++) { + ipa3_ctx->icc_clk[i][j][IPA_ICC_AB] = + resource_p->icc_clk_val[i][j*IPA_ICC_TYPE_MAX]; + ipa3_ctx->icc_clk[i][j][IPA_ICC_IB] = + resource_p->icc_clk_val[i][j*IPA_ICC_TYPE_MAX+1]; + } + } + ipa3_ctx->ctrl = kzalloc(sizeof(*ipa3_ctx->ctrl), GFP_KERNEL); if (!ipa3_ctx->ctrl) { result = -ENOMEM; @@ -6562,15 +6602,19 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p, if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL && ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_EMULATION) { /* get BUS handle */ - ipa3_ctx->ctrl->pcie_path = of_icc_get( - &ipa3_ctx->master_pdev->dev, NULL); - if (IS_ERR(ipa3_ctx->ctrl->pcie_path)) { - IPAERR("fail to register with bus mgr!\n"); - result = PTR_ERR(ipa3_ctx->ctrl->pcie_path); - if (result != -EPROBE_DEFER) - IPAERR("PCIe: Failed to failed path %s\n", - ipa3_ctx->master_pdev->name); - goto fail_bus_reg; + for (i = 0; i < ipa3_ctx->icc_num_paths; i++) { + ipa3_ctx->ctrl->icc_path[i] = of_icc_get( + &ipa3_ctx->master_pdev->dev, + resource_p->icc_path_name[i]); + if (IS_ERR(ipa3_ctx->ctrl->icc_path[i])) { + IPAERR("fail to register with bus mgr!\n"); + result = PTR_ERR(ipa3_ctx->ctrl->icc_path[i]); + if (result != -EPROBE_DEFER) { + IPAERR("Failed to get path %s\n", + ipa3_ctx->master_pdev->name); + } + goto fail_bus_reg; + } } } @@ -6953,8 +6997,11 @@ fail_init_active_client: clk_put(ipa3_clk); ipa3_clk = NULL; fail_bus_reg: - if (ipa3_ctx->ctrl->pcie_path) - icc_put(ipa3_ctx->ctrl->pcie_path); + for (i = 0; i < ipa3_ctx->icc_num_paths; i++) + if (ipa3_ctx->ctrl->icc_path[i]) { + icc_put(ipa3_ctx->ctrl->icc_path[i]); + ipa3_ctx->ctrl->icc_path[i] = NULL; + } fail_init_mem_partition: fail_bind: kfree(ipa3_ctx->ctrl); @@ -6975,18 +7022,101 @@ static int get_ipa_dts_pm_info(struct platform_device *pdev, int result; int i, j; + /* this interconnects entry must be presented */ + if (!of_find_property(pdev->dev.of_node, + "interconnects", NULL)) { + IPAERR("No interconnect info\n"); + return -EFAULT; + } + result = of_property_read_u32(pdev->dev.of_node, - "qcom,msm-bus,num-cases", - &ipa_drv_res->pm_init.threshold_size); + "qcom,interconnect,num-cases", + &ipa_drv_res->icc_num_cases); /* No vote is ignored */ - ipa_drv_res->pm_init.threshold_size -= 2; + ipa_drv_res->pm_init.threshold_size = + ipa_drv_res->icc_num_cases - 2; if (result || ipa_drv_res->pm_init.threshold_size > IPA_PM_THRESHOLD_MAX) { - IPAERR("invalid property qcom,msm-bus,num-cases %d\n", + IPAERR("invalid qcom,interconnect,num-cases %d\n", ipa_drv_res->pm_init.threshold_size); return -EFAULT; } + result = of_property_read_u32(pdev->dev.of_node, + "qcom,interconnect,num-paths", + &ipa_drv_res->icc_num_paths); + if (result || ipa_drv_res->icc_num_paths > + IPA_ICC_PATH_MAX) { + IPAERR("invalid qcom,interconnect,num-paths %d\n", + ipa_drv_res->icc_num_paths); + return -EFAULT; + } + + for (i = 0; i < ipa_drv_res->icc_num_paths; i++) { + result = of_property_read_string_index(pdev->dev.of_node, + "interconnect-names", + i, + &ipa_drv_res->icc_path_name[i]); + if (result) { + IPAERR("invalid interconnect-names %d\n", i); + return -EFAULT; + } + } + /* read no-vote AB IB value */ + result = of_property_read_u32_array(pdev->dev.of_node, + "qcom,no-vote", + ipa_drv_res->icc_clk_val[IPA_ICC_NONE], + ipa_drv_res->icc_num_paths * + IPA_ICC_TYPE_MAX); + if (result) { + IPAERR("invalid property qcom,no-vote\n"); + return -EFAULT; + } + + /* read svs2 AB IB value */ + result = of_property_read_u32_array(pdev->dev.of_node, + "qcom,svs2", + ipa_drv_res->icc_clk_val[IPA_ICC_SVS2], + ipa_drv_res->icc_num_paths * + IPA_ICC_TYPE_MAX); + if (result) { + IPAERR("invalid property qcom,svs2\n"); + return -EFAULT; + } + + /* read svs AB IB value */ + result = of_property_read_u32_array(pdev->dev.of_node, + "qcom,svs", + ipa_drv_res->icc_clk_val[IPA_ICC_SVS], + ipa_drv_res->icc_num_paths * + IPA_ICC_TYPE_MAX); + if (result) { + IPAERR("invalid property qcom,svs\n"); + return -EFAULT; + } + + /* read nominal AB IB value */ + result = of_property_read_u32_array(pdev->dev.of_node, + "qcom,nominal", + ipa_drv_res->icc_clk_val[IPA_ICC_NOMINAL], + ipa_drv_res->icc_num_paths * + IPA_ICC_TYPE_MAX); + if (result) { + IPAERR("invalid property qcom,nominal\n"); + return -EFAULT; + } + + /* read turbo AB IB value */ + result = of_property_read_u32_array(pdev->dev.of_node, + "qcom,turbo", + ipa_drv_res->icc_clk_val[IPA_ICC_TURBO], + ipa_drv_res->icc_num_paths * + IPA_ICC_TYPE_MAX); + if (result) { + IPAERR("invalid property qcom,turbo\n"); + return -EFAULT; + } + result = of_property_read_u32_array(pdev->dev.of_node, "qcom,throughput-threshold", ipa_drv_res->pm_init.default_threshold, diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 83456f22e1b8..be53dcf74445 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -444,6 +444,31 @@ enum ipa_flag { IPA_FLTRT_NOT_HASHABLE_EN, }; +enum ipa_icc_level { + IPA_ICC_NONE, + IPA_ICC_SVS2, + IPA_ICC_SVS, + IPA_ICC_NOMINAL, + IPA_ICC_TURBO, + IPA_ICC_LVL_MAX, +}; + +enum ipa_icc_path { + IPA_ICC_IPA_TO_LLCC, + IPA_ICC_LLCC_TO_EBIL, + IPA_ICC_IPA_TO_IMEM, + IPA_ICC_APSS_TO_IPA, + IPA_ICC_PATH_MAX, +}; + +enum ipa_icc_type { + IPA_ICC_AB, + IPA_ICC_IB, + IPA_ICC_TYPE_MAX, +}; + +#define IPA_ICC_MAX (IPA_ICC_PATH_MAX*IPA_ICC_TYPE_MAX) + struct ipa3_active_client_htable_entry { struct hlist_node list; char id_string[IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN]; @@ -1769,6 +1794,10 @@ struct ipa3_pc_mbox_data { * @lan_rx_napi_enable: flag if NAPI is enabled on the LAN dp * @lan_ndev: dummy netdev for LAN rx NAPI * @napi_lan_rx: NAPI object for LAN rx + * @ipa_wan_skb_page - page recycling enabled on wwan data path + * @icc_num_cases - number of icc scaling level supported + * @icc_num_paths - number of paths icc would vote for bw + * @icc_clk - table for icc bw clock value */ struct ipa3_context { struct ipa3_char_device_context cdev; @@ -1942,6 +1971,9 @@ struct ipa3_context { bool lan_rx_napi_enable; struct net_device lan_ndev; struct napi_struct napi_lan_rx; + u32 icc_num_cases; + u32 icc_num_paths; + u32 icc_clk[IPA_ICC_LVL_MAX][IPA_ICC_PATH_MAX][IPA_ICC_TYPE_MAX]; }; struct ipa3_plat_drv_res { @@ -1990,6 +2022,10 @@ struct ipa3_plat_drv_res { bool ipa_endp_delay_wa; bool skip_ieob_mask_wa; bool ipa_wan_skb_page; + u32 icc_num_cases; + u32 icc_num_paths; + const char *icc_path_name[IPA_ICC_PATH_MAX]; + u32 icc_clk_val[IPA_ICC_LVL_MAX][IPA_ICC_MAX]; }; /** @@ -2236,7 +2272,7 @@ struct ipa3_controller { int (*ipa3_commit_hdr)(void); void (*ipa3_enable_clks)(void); void (*ipa3_disable_clks)(void); - struct icc_path *pcie_path; + struct icc_path *icc_path[IPA_ICC_PATH_MAX]; }; extern struct ipa3_context *ipa3_ctx;