From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 03 Jan 2024 09:43:39 +0000 Subject: [PATCH] update kernel to 5.10.198 --- kernel/drivers/soc/rockchip/rockchip_opp_select.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 202 insertions(+), 26 deletions(-) diff --git a/kernel/drivers/soc/rockchip/rockchip_opp_select.c b/kernel/drivers/soc/rockchip/rockchip_opp_select.c index 8caae5c..6c496ad 100644 --- a/kernel/drivers/soc/rockchip/rockchip_opp_select.c +++ b/kernel/drivers/soc/rockchip/rockchip_opp_select.c @@ -12,6 +12,7 @@ #include <linux/nvmem-consumer.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> +#include <linux/rockchip/rockchip_sip.h> #include <linux/slab.h> #include <linux/soc/rockchip/pvtm.h> #include <linux/thermal.h> @@ -1004,15 +1005,15 @@ } if (of_property_read_u32(np, "rockchip,pvtpll-len-min-rate", &min_rate)) - return; + goto out; if (of_property_read_u32(np, "rockchip,pvtpll-len-max-rate", &max_rate)) - return; + goto out; if (of_property_read_u32(np, "rockchip,pvtpll-len-margin", &margin)) - return; + goto out; opp_table = dev_pm_opp_get_opp_table(info->dev); if (!opp_table) - return; + goto out; old_rate = clk_get_rate(opp_table->clk); opp_flag = OPP_ADD_LENGTH | ((margin & OPP_LENGTH_MASK) << OPP_LENGTH_SHIFT); @@ -1033,8 +1034,97 @@ clk_set_rate(opp_table->clk, old_rate); dev_pm_opp_put_opp_table(opp_table); +out: + of_node_put(np); } EXPORT_SYMBOL(rockchip_pvtpll_add_length); + +void rockchip_init_pvtpll_table(struct rockchip_opp_info *info, int bin) +{ + struct device_node *np = NULL; + struct property *prop = NULL; + struct of_phandle_args clkspec = { 0 }; + struct arm_smccc_res res; + char prop_name[NAME_MAX]; + u32 *value; + int count; + int ret, i; + + if (!info) + return; + + np = of_parse_phandle(info->dev->of_node, "operating-points-v2", 0); + if (!np) { + dev_warn(info->dev, "OPP-v2 not supported\n"); + return; + } + + ret = of_parse_phandle_with_args(info->dev->of_node, "clocks", + "#clock-cells", 0, &clkspec); + if (ret) + goto out; + info->pvtpll_clk_id = clkspec.args[0]; + of_node_put(clkspec.np); + + res = sip_smc_get_pvtpll_info(PVTPLL_GET_INFO, info->pvtpll_clk_id); + if (res.a0) + goto out; + if (!res.a1) + info->pvtpll_low_temp = true; + + if (bin > 0) { + snprintf(prop_name, sizeof(prop_name), + "rockchip,pvtpll-table-B%d", bin); + prop = of_find_property(np, prop_name, NULL); + } + if (!prop) + sprintf(prop_name, "rockchip,pvtpll-table"); + + prop = of_find_property(np, prop_name, NULL); + if (!prop) + goto out; + + count = of_property_count_u32_elems(np, prop_name); + if (count < 0) { + dev_err(info->dev, "%s: Invalid %s property (%d)\n", + __func__, prop_name, count); + goto out; + } else if (count % 5) { + dev_err(info->dev, "Invalid count of %s\n", prop_name); + goto out; + } + + value = kmalloc_array(count, sizeof(*value), GFP_KERNEL); + if (!value) + goto out; + ret = of_property_read_u32_array(np, prop_name, value, count); + if (ret) { + dev_err(info->dev, "%s: error parsing %s: %d\n", + __func__, prop_name, ret); + goto free_value; + } + + for (i = 0; i < count; i += 5) { + res = sip_smc_pvtpll_config(PVTPLL_ADJUST_TABLE, + info->pvtpll_clk_id, value[i], + value[i + 1], value[i + 2], + value[i + 3], value[i + 4]); + if (res.a0) { + dev_err(info->dev, + "%s: error cfg clk_id=%u %u %u %u %u %u (%d)\n", + __func__, info->pvtpll_clk_id, value[i], + value[i + 1], value[i + 2], value[i + 3], + value[i + 4], (int)res.a0); + goto free_value; + } + } + +free_value: + kfree(value); +out: + of_node_put(np); +} +EXPORT_SYMBOL(rockchip_init_pvtpll_table); static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np, char *reg_name) @@ -1186,10 +1276,15 @@ snprintf(name, sizeof(name), "rockchip,p%d-pvtm-voltage-sel", process); prop = of_find_property(np, name, NULL); - } else if (bin >= 0) { + } else if (bin > 0) { of_property_read_u32(np, "rockchip,pvtm-hw", &hw); if (hw && (hw & BIT(bin))) { sprintf(name, "rockchip,pvtm-voltage-sel-hw"); + prop = of_find_property(np, name, NULL); + } + if (!prop) { + snprintf(name, sizeof(name), + "rockchip,pvtm-voltage-sel-B%d", bin); prop = of_find_property(np, name, NULL); } } @@ -1633,6 +1728,10 @@ rockchip_adjust_opp_by_irdrop(dev, np, &safe_rate, &max_rate); dev_info(dev, "avs=%d\n", avs); + + if (!safe_rate && !scale) + goto out_np; + clk = of_clk_get_by_name(np, NULL); if (IS_ERR(clk)) { if (!safe_rate) @@ -1646,14 +1745,14 @@ if (safe_rate) irdrop_scale = rockchip_pll_clk_rate_to_scale(clk, safe_rate); - if (max_rate) - opp_scale = rockchip_pll_clk_rate_to_scale(clk, max_rate); target_scale = max(irdrop_scale, scale); if (target_scale <= 0) goto out_clk; dev_dbg(dev, "target_scale=%d, irdrop_scale=%d, scale=%d\n", target_scale, irdrop_scale, scale); + if (max_rate) + opp_scale = rockchip_pll_clk_rate_to_scale(clk, max_rate); if (avs == AVS_SCALING_RATE) { ret = rockchip_pll_clk_adaptive_scaling(clk, target_scale); if (ret) @@ -1838,13 +1937,78 @@ } EXPORT_SYMBOL(rockchip_set_intermediate_rate); +static int rockchip_get_opp_clk(struct device *dev, struct device_node *np, + struct rockchip_opp_info *info) +{ + struct clk_bulk_data *clks; + struct of_phandle_args clkspec; + int ret = 0, num_clks = 0, i; + + if (of_find_property(np, "rockchip,opp-clocks", NULL)) { + num_clks = of_count_phandle_with_args(np, "rockchip,opp-clocks", + "#clock-cells"); + if (num_clks <= 0) + return 0; + clks = devm_kcalloc(dev, num_clks, sizeof(*clks), GFP_KERNEL); + if (!clks) + return -ENOMEM; + for (i = 0; i < num_clks; i++) { + ret = of_parse_phandle_with_args(np, + "rockchip,opp-clocks", + "#clock-cells", i, + &clkspec); + if (ret < 0) { + dev_err(dev, "%s: failed to parse opp clk %d\n", + np->name, i); + goto error; + } + clks[i].clk = of_clk_get_from_provider(&clkspec); + of_node_put(clkspec.np); + if (IS_ERR(clks[i].clk)) { + ret = PTR_ERR(clks[i].clk); + clks[i].clk = NULL; + dev_err(dev, "%s: failed to get opp clk %d\n", + np->name, i); + goto error; + } + } + } else { + num_clks = of_clk_get_parent_count(np); + if (num_clks <= 0) + return 0; + clks = devm_kcalloc(dev, num_clks, sizeof(*clks), GFP_KERNEL); + if (!clks) + return -ENOMEM; + for (i = 0; i < num_clks; i++) { + clks[i].clk = of_clk_get(np, i); + if (IS_ERR(clks[i].clk)) { + ret = PTR_ERR(clks[i].clk); + clks[i].clk = NULL; + dev_err(dev, "%s: failed to get clk %d\n", + np->name, i); + goto error; + } + } + } + info->clks = clks; + info->num_clks = num_clks; + + return 0; +error: + while (--i >= 0) + clk_put(clks[i].clk); + devm_kfree(dev, clks); + + return ret; +} + int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info, char *lkg_name, char *reg_name) { struct device_node *np; int bin = -EINVAL, process = -EINVAL; int scale = 0, volt_sel = -EINVAL; - int ret = 0, num_clks = 0, i; + int ret = 0; u32 freq; /* Get OPP descriptor node */ @@ -1857,24 +2021,10 @@ goto next; info->dev = dev; - num_clks = of_clk_get_parent_count(np); - if (num_clks > 0) { - info->clks = devm_kcalloc(dev, num_clks, sizeof(*info->clks), - GFP_KERNEL); - if (!info->clks) { - ret = -ENOMEM; - goto out; - } - for (i = 0; i < num_clks; i++) { - info->clks[i].clk = of_clk_get(np, i); - if (IS_ERR(info->clks[i].clk)) { - ret = PTR_ERR(info->clks[i].clk); - dev_err(dev, "%s: failed to get clk %d\n", - np->name, i); - goto out; - } - } - info->num_clks = num_clks; + ret = rockchip_get_opp_clk(dev, np, info); + if (ret) + goto out; + if (info->clks) { ret = clk_bulk_prepare_enable(info->num_clks, info->clks); if (ret) { dev_err(dev, "failed to enable opp clks\n"); @@ -1900,6 +2050,7 @@ next: rockchip_get_soc_info(dev, np, &bin, &process); + rockchip_init_pvtpll_table(info, bin); rockchip_get_scale_volt_sel(dev, lkg_name, reg_name, bin, process, &scale, &volt_sel); if (info && info->data && info->data->set_soc_info) @@ -1925,6 +2076,31 @@ } EXPORT_SYMBOL(rockchip_init_opp_table); +void rockchip_uninit_opp_table(struct device *dev, struct rockchip_opp_info *info) +{ + struct opp_table *opp_table; + + if (info) { + kfree(info->opp_table); + info->opp_table = NULL; + devm_kfree(dev, info->clks); + info->clks = NULL; + devm_kfree(dev, info->volt_rm_tbl); + info->volt_rm_tbl = NULL; + } + + opp_table = dev_pm_opp_get_opp_table(dev); + if (IS_ERR(opp_table)) + return; + dev_pm_opp_of_remove_table(dev); + if (opp_table->prop_name) + dev_pm_opp_put_prop_name(opp_table); + if (opp_table->supported_hw) + dev_pm_opp_put_supported_hw(opp_table); + dev_pm_opp_put_opp_table(opp_table); +} +EXPORT_SYMBOL(rockchip_uninit_opp_table); + MODULE_DESCRIPTION("ROCKCHIP OPP Select"); MODULE_AUTHOR("Finley Xiao <finley.xiao@rock-chips.com>, Liang Chen <cl@rock-chips.com>"); MODULE_LICENSE("GPL"); -- Gitblit v1.6.2