From 4149cbb903dfddfe9eeec78ccbc4604c3ff9cf7f Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 28 Nov 2023 17:07:59 +0800 Subject: [PATCH 1/3] soc: rockchip: opp_select: Implement rockchip_init_pvtpll_table() This patch adds support to parse pvtpll config from devicetree, and change config through sip smc interface. Signed-off-by: Finley Xiao Change-Id: I5f23b9eb1d358a95b690ca214e35927e74451af1 --- drivers/soc/rockchip/rockchip_opp_select.c | 89 ++++++++++++++++++++++ include/soc/rockchip/rockchip_opp_select.h | 8 ++ 2 files changed, 97 insertions(+) diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 0e6273bf62c8..9ca37ab3296c 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -1038,6 +1039,93 @@ out: } 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) { @@ -1957,6 +2045,7 @@ int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info, 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) diff --git a/include/soc/rockchip/rockchip_opp_select.h b/include/soc/rockchip/rockchip_opp_select.h index 6d595f94f12c..e7669f29cbd5 100644 --- a/include/soc/rockchip/rockchip_opp_select.h +++ b/include/soc/rockchip/rockchip_opp_select.h @@ -78,6 +78,8 @@ struct rockchip_opp_info { u32 low_rm; u32 current_rm; u32 target_rm; + u32 pvtpll_clk_id; + bool pvtpll_low_temp; }; #if IS_ENABLED(CONFIG_ROCKCHIP_OPP) @@ -87,6 +89,7 @@ void rockchip_of_get_lkg_sel(struct device *dev, struct device_node *np, int *volt_sel, int *scale_sel); void rockchip_pvtpll_calibrate_opp(struct rockchip_opp_info *info); void rockchip_pvtpll_add_length(struct rockchip_opp_info *info); +void rockchip_init_pvtpll_table(struct rockchip_opp_info *info, int bin); void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np, char *reg_name, int bin, int process, int *volt_sel, int *scale_sel); @@ -154,6 +157,11 @@ static inline void rockchip_pvtpll_add_length(struct rockchip_opp_info *info) { } +static inline void rockchip_init_pvtpll_table(struct rockchip_opp_info *info, + int bin) +{ +} + static inline void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np, char *reg_name, int bin, int process, From 4df54d5e562d48689fb642daa81b7457210ba446 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Tue, 28 Nov 2023 17:20:19 +0800 Subject: [PATCH 2/3] cpufreq: rockchip: Add support to init pvtpll table This patch adds support to parse pvtpll config from devicetree, and change config through sip smc interface. Signed-off-by: Finley Xiao Change-Id: I74f2127d862db005433d0a9da2703629f80b0faa --- drivers/cpufreq/rockchip-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index 804fcfd1ed1c..27c6d92edfb7 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -606,6 +606,7 @@ static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster) if (opp_info->data && opp_info->data->get_soc_info) opp_info->data->get_soc_info(dev, np, &bin, &process); rockchip_get_soc_info(dev, np, &bin, &process); + rockchip_init_pvtpll_table(&cluster->opp_info, bin); rockchip_get_scale_volt_sel(dev, "cpu_leakage", reg_name, bin, process, &cluster->scale, &volt_sel); if (opp_info->data && opp_info->data->set_soc_info) From feecbd010e4ef7f167611fad0ec94a2a8743d3ae Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Wed, 29 Nov 2023 21:04:32 +0800 Subject: [PATCH 3/3] soc: rockchip: rockchip_system_monitor: Add support to use low temp pvtpll config Change-Id: Ifa96a101008587309ca10ae6c2bd76424da6039b Signed-off-by: Finley Xiao --- drivers/soc/rockchip/rockchip_system_monitor.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/soc/rockchip/rockchip_system_monitor.c b/drivers/soc/rockchip/rockchip_system_monitor.c index da95bbda81f8..527764e235c7 100644 --- a/drivers/soc/rockchip/rockchip_system_monitor.c +++ b/drivers/soc/rockchip/rockchip_system_monitor.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -919,6 +920,7 @@ static void rockchip_low_temp_adjust(struct monitor_dev_info *info, bool is_low) { struct monitor_dev_profile *devp = info->devp; + struct arm_smccc_res res; int ret = 0; dev_dbg(info->dev, "low_temp %d\n", is_low); @@ -933,6 +935,17 @@ static void rockchip_low_temp_adjust(struct monitor_dev_info *info, if (devp->update_volt) devp->update_volt(info); + + if (devp->opp_info->pvtpll_low_temp) { + res = sip_smc_pvtpll_config(PVTPLL_LOW_TEMP, + devp->opp_info->pvtpll_clk_id, + is_low, 0, 0, 0, 0); + if (res.a0) + dev_err(info->dev, + "%s: error cfg id=%u low temp %d (%d)\n", + __func__, devp->opp_info->pvtpll_clk_id, + is_low, (int)res.a0); + } } static void rockchip_high_temp_adjust(struct monitor_dev_info *info,