diff options
23 files changed, 560 insertions, 372 deletions
diff --git a/arch/arm/boot/dts/rk3288-android.dtsi b/arch/arm/boot/dts/rk3288-android.dtsi index 02938b0cbe92..a63cb6955559 100644 --- a/arch/arm/boot/dts/rk3288-android.dtsi +++ b/arch/arm/boot/dts/rk3288-android.dtsi @@ -394,6 +394,7 @@ }; &cpu0_opp_table { + rockchip,avs-enable = <1>; clocks = <&cru PLL_APLL>; leakage-scaling-sel = <0 254 25>; diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index e6ca69ba8ee1..6b075ef68157 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -131,6 +131,7 @@ compatible = "operating-points-v2"; opp-shared; + rockchip,avs-scale = <17>; nvmem-cells = <&cpu_leakage>; nvmem-cell-names = "cpu_leakage"; diff --git a/arch/arm64/boot/dts/rockchip/px30-android.dtsi b/arch/arm64/boot/dts/rockchip/px30-android.dtsi index 8c9c92e2cd3c..71d4cc489ff1 100644 --- a/arch/arm64/boot/dts/rockchip/px30-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30-android.dtsi @@ -71,6 +71,10 @@ }; }; +&cpu0_opp_table { + rockchip,avs-enable = <1>; +}; + &display_subsystem { status = "disabled"; ports = <&vopb_out>, <&vopl_out>; diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi index 96808ba408f6..d4254f0b4359 100644 --- a/arch/arm64/boot/dts/rockchip/px30.dtsi +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi @@ -109,6 +109,7 @@ opp-shared; clocks = <&cru PLL_APLL>; + rockchip,avs-scale = <4>; rockchip,max-volt = <1350000>; rockchip,evb-irdrop = <25000>; nvmem-cells = <&cpu_leakage>; diff --git a/arch/arm64/boot/dts/rockchip/rk3368-android.dtsi b/arch/arm64/boot/dts/rockchip/rk3368-android.dtsi index fb5d64950d81..b7a8ab6971f4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368-android.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368-android.dtsi @@ -173,6 +173,10 @@ }; }; +&cluster1_opp { + rockchip,avs-enable = <1>; +}; + &display_subsystem { status = "okay"; diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi index a880a393bf0c..c5277499125e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi @@ -275,6 +275,7 @@ cluster1_opp: opp_table1 { compatible = "operating-points-v2"; opp-shared; + rockchip,avs-sclae = <36>; rockchip,leakage-scaling-sel = < 1 24 36 25 254 0 diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index da7221078b33..dea6ce39cb04 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -114,12 +114,12 @@ int rockchip_pll_clk_adaptive_scaling(struct clk *clk, int sel) return 0; } -int rockchip_pll_clk_adaptive_rate(struct clk *clk, unsigned long rate) +int rockchip_pll_clk_rate_to_scale(struct clk *clk, unsigned long rate) { const struct rockchip_pll_rate_table *rate_table; struct clk *parent = clk_get_parent(clk); struct rockchip_clk_pll *pll; - int i; + unsigned int i; if (IS_ERR_OR_NULL(parent)) return -EINVAL; @@ -130,13 +130,34 @@ int rockchip_pll_clk_adaptive_rate(struct clk *clk, unsigned long rate) rate_table = pll->rate_table; for (i = 0; i < pll->rate_count; i++) { - if (rate >= rate_table[i].rate) { - pll->sel = i; - break; - } + if (rate >= rate_table[i].rate) + return i; } - return 0; + return -EINVAL; +} + +int rockchip_pll_clk_scale_to_rate(struct clk *clk, unsigned int scale) +{ + const struct rockchip_pll_rate_table *rate_table; + struct clk *parent = clk_get_parent(clk); + struct rockchip_clk_pll *pll; + unsigned int i; + + if (IS_ERR_OR_NULL(parent)) + return -EINVAL; + + pll = to_rockchip_clk_pll(__clk_get_hw(parent)); + if (!pll) + return -EINVAL; + + rate_table = pll->rate_table; + for (i = 0; i < pll->rate_count; i++) { + if (i == scale) + return rate_table[i].rate; + } + + return -EINVAL; } static struct rockchip_pll_rate_table *rk_pll_rate_table_get(void) diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 779497c5512b..e4bcd2a5abb1 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -781,7 +781,8 @@ void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, int nrates); void rockchip_clk_protect_critical(const char *const clocks[], int nclocks); int rockchip_pll_clk_adaptive_scaling(struct clk *clk, int sel); -int rockchip_pll_clk_adaptive_rate(struct clk *clk, unsigned long rate); +int rockchip_pll_clk_rate_to_scale(struct clk *clk, unsigned long rate); +int rockchip_pll_clk_scale_to_rate(struct clk *clk, unsigned int scale); void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, unsigned int reg, void (*cb)(void)); diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index b785a328adc5..f07774f96a14 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -161,7 +161,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) unsigned long cur_freq; bool opp_v1 = false; const char *name; - int ret; + int ret, scale; static int check_init; cpu_dev = get_cpu_device(policy->cpu); @@ -227,7 +227,8 @@ static int cpufreq_init(struct cpufreq_policy *policy) dev_pm_opp_of_remove_table(cpu_dev); } } - rockchip_adjust_opp_by_irdrop(cpu_dev); + scale = rockchip_cpufreq_get_scale(policy->cpu); + rockchip_adjust_power_scale(cpu_dev, scale); #else dev_pm_opp_of_cpumask_add_table(policy->cpus); #endif diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c index bcd8e59303f9..35ad89aa417b 100644 --- a/drivers/cpufreq/rockchip-cpufreq.c +++ b/drivers/cpufreq/rockchip-cpufreq.c @@ -33,7 +33,6 @@ #include "../clk/rockchip/clk.h" -#define MAX_PROP_NAME_LEN 3 #define LEAKAGE_INVALID 0xff #define REBOOT_FREQ 816000 /* kHz */ @@ -42,10 +41,9 @@ struct cluster_info { cpumask_t cpus; unsigned int reboot_freq; unsigned int threshold_freq; - int leakage; - int pvtm; int volt_sel; - int soc_version; + int scale; + int process; bool offline; bool rebooting; bool freq_limit; @@ -64,68 +62,27 @@ static struct cluster_info *rockchip_cluster_info_lookup(int cpu) return NULL; } -static int rockchip_get_efuse_value(struct device_node *np, char *porp_name, - int *value) +int rockchip_cpufreq_get_scale(int cpu) { - struct nvmem_cell *cell; - unsigned char *buf; - size_t len; - - cell = of_nvmem_cell_get(np, porp_name); - if (IS_ERR(cell)) - return PTR_ERR(cell); - - buf = (unsigned char *)nvmem_cell_read(cell, &len); - - nvmem_cell_put(cell); - - if (IS_ERR(buf)) - return PTR_ERR(buf); - - if (buf[0] == LEAKAGE_INVALID) - return -EINVAL; - - *value = buf[0]; - - kfree(buf); - - return 0; -} - -static int rk3399_get_soc_version(struct device_node *np, int *soc_version) -{ - int ret, version; + struct cluster_info *cluster; - if (of_property_match_string(np, "nvmem-cell-names", - "soc_version") < 0) + cluster = rockchip_cluster_info_lookup(cpu); + if (!cluster) return 0; - - ret = rockchip_get_efuse_value(np, "soc_version", &version); - if (ret) - return ret; - - *soc_version = (version & 0xf0) >> 4; - - return 0; + else + return cluster->scale; } - -static const struct of_device_id rockchip_cpufreq_of_match[] = { - { - .compatible = "rockchip,rk3399", - .data = (void *)&rk3399_get_soc_version, - }, - {}, -}; +EXPORT_SYMBOL_GPL(rockchip_cpufreq_get_scale); static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster) { - int (*get_soc_version)(struct device_node *np, int *soc_version); - const struct of_device_id *match; - struct device_node *node, *np; - struct clk *clk; + struct device_node *np; struct device *dev; - int lkg_volt_sel, pvtm_volt_sel, lkg_scale_sel; - int ret; + int ret = 0, bin = -EINVAL; + + cluster->process = -EINVAL; + cluster->volt_sel = -EINVAL; + cluster->scale = 0; dev = get_cpu_device(cpu); if (!dev) @@ -138,19 +95,9 @@ static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster) } ret = dev_pm_opp_of_get_sharing_cpus(dev, &cluster->cpus); - if (ret) - return ret; - - cluster->soc_version = -1; - node = of_find_node_by_path("/"); - match = of_match_node(rockchip_cpufreq_of_match, node); - if (match && match->data) { - get_soc_version = match->data; - ret = get_soc_version(np, &cluster->soc_version); - if (ret) { - dev_err(dev, "Failed to get chip_version\n"); - return ret; - } + if (ret) { + dev_err(dev, "Failed to get sharing cpus\n"); + goto np_err; } if (of_property_read_u32(np, "rockchip,reboot-freq", @@ -160,68 +107,23 @@ static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster) &cluster->threshold_freq); cluster->freq_limit = of_property_read_bool(np, "rockchip,freq-limit"); - lkg_scale_sel = rockchip_of_get_lkg_scale_sel(dev, "cpu_leakage"); - if (lkg_scale_sel > 0) { - clk = of_clk_get_by_name(np, NULL); - if (IS_ERR(clk)) { - dev_err(dev, "Failed to get opp clk"); - return PTR_ERR(clk); - } - ret = rockchip_pll_clk_adaptive_scaling(clk, - lkg_scale_sel); - if (ret) { - dev_err(dev, "Failed to adaptive scaling\n"); - return ret; - } - } - - lkg_volt_sel = rockchip_of_get_lkg_volt_sel(dev, "cpu_leakage"); - pvtm_volt_sel = rockchip_of_get_pvtm_volt_sel(dev, NULL, "cpu"); - - cluster->volt_sel = max(lkg_volt_sel, pvtm_volt_sel); - - return 0; + rockchip_get_soc_info(dev, NULL, &bin, &cluster->process); + rockchip_get_scale_volt_sel(dev, "cpu_leakage", "cpu", + bin, cluster->process, + &cluster->scale, &cluster->volt_sel); +np_err: + of_node_put(np); + return ret; } static int rockchip_cpufreq_set_opp_info(int cpu, struct cluster_info *cluster) { - struct device *dev; - char name[MAX_PROP_NAME_LEN]; - int ret, version; + struct device *dev = get_cpu_device(cpu); - dev = get_cpu_device(cpu); if (!dev) return -ENODEV; - - if (cluster->soc_version >= 0) { - if (cluster->volt_sel >= 0) - snprintf(name, MAX_PROP_NAME_LEN, "S%d-L%d", - cluster->soc_version, cluster->volt_sel); - else - snprintf(name, MAX_PROP_NAME_LEN, "S%d", - cluster->soc_version); - } else if (cluster->volt_sel >= 0) { - snprintf(name, MAX_PROP_NAME_LEN, "L%d", cluster->volt_sel); - } else { - return 0; - } - - ret = dev_pm_opp_set_prop_name(dev, name); - if (ret) { - dev_err(dev, "Failed to set prop name\n"); - return ret; - } - - if (cluster->soc_version >= 0) { - version = BIT(cluster->soc_version); - ret = dev_pm_opp_set_supported_hw(dev, &version, 1); - if (ret) { - dev_err(dev, "Failed to set supported hardware\n"); - return ret; - } - } - - return 0; + return rockchip_set_opp_info(dev, cluster->process, + cluster->volt_sel); } static int rockchip_hotcpu_notifier(struct notifier_block *nb, diff --git a/drivers/devfreq/rockchip_dmc.c b/drivers/devfreq/rockchip_dmc.c index 3dd5c69953ed..3f03b81400b7 100644 --- a/drivers/devfreq/rockchip_dmc.c +++ b/drivers/devfreq/rockchip_dmc.c @@ -2933,10 +2933,7 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) int (*init)(struct platform_device *pdev, struct rockchip_dmcfreq *data); unsigned long opp_rate, opp_volt; -#define MAX_PROP_NAME_LEN 3 - char name[MAX_PROP_NAME_LEN]; bool is_events_available = false; - int lkg_volt_sel, pvtm_volt_sel, volt_sel; int ret; data = devm_kzalloc(dev, sizeof(struct rockchip_dmcfreq), GFP_KERNEL); @@ -2987,22 +2984,11 @@ static int rockchip_dmcfreq_probe(struct platform_device *pdev) * We add a devfreq driver to our parent since it has a device tree node * with operating points. */ - lkg_volt_sel = rockchip_of_get_lkg_volt_sel(dev, "ddr_leakage"); - pvtm_volt_sel = rockchip_of_get_pvtm_volt_sel(dev, NULL, "center"); - - volt_sel = max(lkg_volt_sel, pvtm_volt_sel); - if (volt_sel >= 0) { - snprintf(name, MAX_PROP_NAME_LEN, "L%d", volt_sel); - ret = dev_pm_opp_set_prop_name(dev, name); - if (ret) - dev_err(dev, "Failed to set prop name\n"); - } - - if (dev_pm_opp_of_add_table(dev)) { - dev_err(dev, "Invalid operating-points in device tree.\n"); - return -EINVAL; + ret = rockchip_init_opp_table(dev, NULL, "ddr_leakage", "center"); + if (ret) { + dev_err(dev, "Failed to init_opp_table (%d)\n", ret); + return ret; } - rockchip_adjust_opp_by_irdrop(dev); if (rockchip_dmcfreq_init_freq_table(dev, devp)) return -EFAULT; diff --git a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.h b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.h index 7493ce900fd7..ed484366db24 100644 --- a/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.h +++ b/drivers/gpu/arm/bifrost/backend/gpu/mali_kbase_devfreq.h @@ -25,6 +25,6 @@ int kbase_devfreq_init(struct kbase_device *kbdev); void kbase_devfreq_term(struct kbase_device *kbdev); -void kbase_platform_rk_set_opp_info(struct kbase_device *kbdev); +int kbase_platform_rk_init_opp_table(struct kbase_device *kbdev); #endif /* _BASE_DEVFREQ_H_ */ diff --git a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c index 7df2e39c45dd..0a744c35ae1d 100644 --- a/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/bifrost/mali_kbase_core_linux.c @@ -3254,22 +3254,9 @@ static int power_control_init(struct platform_device *pdev) } } - kbase_platform_rk_set_opp_info(kbdev); - -#if defined(CONFIG_OF) && defined(CONFIG_PM_OPP) - /* Register the OPPs if they are available in device tree */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) \ - || defined(LSK_OPPV2_BACKPORT) - err = dev_pm_opp_of_add_table(kbdev->dev); - rockchip_adjust_opp_by_irdrop(kbdev->dev); -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) - err = of_init_opp_table(kbdev->dev); -#else - err = 0; -#endif /* LINUX_VERSION_CODE */ + err = kbase_platform_rk_init_opp_table(kbdev); if (err) - dev_dbg(kbdev->dev, "OPP table not found\n"); -#endif /* CONFIG_OF && CONFIG_PM_OPP */ + dev_err(kbdev->dev, "Failed to init_opp_table (%d)\n", err); return 0; diff --git a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c index f9607d6fdf09..e7fa0c84dc91 100755 --- a/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/bifrost/platform/rk/mali_kbase_config_rk.c @@ -433,24 +433,8 @@ static void kbase_platform_rk_remove_sysfs_files(struct device *dev) device_remove_file(dev, &dev_attr_utilisation); } -void kbase_platform_rk_set_opp_info(struct kbase_device *kbdev) +int kbase_platform_rk_init_opp_table(struct kbase_device *kbdev) { -#define MAX_PROP_NAME_LEN 3 - char name[MAX_PROP_NAME_LEN]; - int lkg_volt_sel, pvtm_volt_sel, volt_sel; - int err = 0; - - if (!kbdev) - return; - - lkg_volt_sel = rockchip_of_get_lkg_volt_sel(kbdev->dev, "gpu_leakage"); - pvtm_volt_sel = rockchip_of_get_pvtm_volt_sel(kbdev->dev, NULL, "mali"); - - volt_sel = max(lkg_volt_sel, pvtm_volt_sel); - if (volt_sel >= 0) { - snprintf(name, MAX_PROP_NAME_LEN, "L%d", volt_sel); - err = dev_pm_opp_set_prop_name(kbdev->dev, name); - if (err) - dev_err(kbdev->dev, "Failed to set prop name\n"); - } + return rockchip_init_opp_table(kbdev->dev, NULL, + "gpu_leakage", "mali"); } diff --git a/drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.c b/drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.c index ecfd5c3456bd..08df33df5d21 100755 --- a/drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.c +++ b/drivers/gpu/arm/mali400/mali/linux/mali_kernel_linux.c @@ -205,6 +205,8 @@ extern int mali_platform_device_unregister(void); #endif #endif +extern int rk_platform_init_opp_table(struct device *dev); + /* Linux power management operations provided by the Mali device driver */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)) struct pm_ext_ops mali_dev_ext_pm_ops = { @@ -518,10 +520,7 @@ static int mali_probe(struct platform_device *pdev) { int err; #ifdef CONFIG_MALI_DEVFREQ -#define MAX_PROP_NAME_LEN 3 struct mali_device *mdev; - char name[MAX_PROP_NAME_LEN]; - int lkg_volt_sel; #endif MALI_DEBUG_PRINT(2, ("mali_probe(): Called for platform device %s\n", pdev->name)); @@ -567,14 +566,6 @@ static int mali_probe(struct platform_device *pdev) mdev->dev = &pdev->dev; dev_set_drvdata(mdev->dev, mdev); - lkg_volt_sel = rockchip_of_get_lkg_volt_sel(mdev->dev, "gpu_leakage"); - if (lkg_volt_sel >= 0) { - snprintf(name, MAX_PROP_NAME_LEN, "L%d", lkg_volt_sel); - err = dev_pm_opp_set_prop_name(mdev->dev, name); - if (err) - dev_err(mdev->dev, "Failed to set prop name\n"); - } - /*Initilization clock and regulator*/ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) && defined(CONFIG_OF) \ && defined(CONFIG_REGULATOR) @@ -586,12 +577,9 @@ static int mali_probe(struct platform_device *pdev) } #endif /* LINUX_VERSION_CODE >= 3, 12, 0 */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) && defined(CONFIG_OF) \ - && defined(CONFIG_PM_OPP) - /* Register the OPPs if they are available in device tree */ - if (dev_pm_opp_of_add_table(mdev->dev) < 0) - MALI_DEBUG_PRINT(3, ("OPP table not found\n")); -#endif + err = rk_platform_init_opp_table(mdev->dev); + if (err) + MALI_DEBUG_PRINT(3, ("Failed to init_opp_table\n")); /* Need to name the gpu clock "clk_mali" in the device tree */ mdev->clock = clk_get(mdev->dev, "clk_mali"); diff --git a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c index 46a8ba8901bb..80eadf12a70f 100644 --- a/drivers/gpu/arm/mali400/mali/platform/rk/rk.c +++ b/drivers/gpu/arm/mali400/mali/platform/rk/rk.c @@ -35,6 +35,7 @@ #include <linux/pm_runtime.h> #include <linux/delay.h> #include <linux/rockchip/cpu.h> +#include <soc/rockchip/rockchip_opp_select.h> #include <linux/mali/mali_utgard.h> #include "mali_kernel_common.h" @@ -444,6 +445,11 @@ static void rk_platform_power_off_gpu(struct device *dev) rk_platform_disable_gpu_regulator(dev); } +int rk_platform_init_opp_table(struct device *dev) +{ + return rockchip_init_opp_table(dev, NULL, "gpu_leakage", "mali"); +} + static int mali_runtime_suspend(struct device *device) { int ret = 0; diff --git a/drivers/gpu/arm/midgard/mali_kbase_core_linux.c b/drivers/gpu/arm/midgard/mali_kbase_core_linux.c index 65b2045a35b7..3a6e5aae0bce 100644 --- a/drivers/gpu/arm/midgard/mali_kbase_core_linux.c +++ b/drivers/gpu/arm/midgard/mali_kbase_core_linux.c @@ -3880,21 +3880,9 @@ static int power_control_init(struct platform_device *pdev) } } - kbase_platform_rk_set_opp_info(kbdev); - -#if defined(CONFIG_OF) && defined(CONFIG_PM_OPP) - /* Register the OPPs if they are available in device tree */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) \ - || defined(LSK_OPPV2_BACKPORT) - err = dev_pm_opp_of_add_table(kbdev->dev); -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) - err = of_init_opp_table(kbdev->dev); -#else - err = 0; -#endif /* LINUX_VERSION_CODE */ + err = kbase_platform_rk_init_opp_table(kbdev); if (err) - dev_dbg(kbdev->dev, "OPP table not found\n"); -#endif /* CONFIG_OF && CONFIG_PM_OPP */ + dev_err(kbdev->dev, "Failed to init_opp_table (%d)\n", err); return 0; diff --git a/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h b/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h index a9569e808fb8..c11085af5f24 100644 --- a/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h +++ b/drivers/gpu/arm/midgard/platform/mali_kbase_platform_common.h @@ -25,4 +25,4 @@ * @return Zero to indicate success non-zero for failure. */ int kbase_platform_early_init(void); -void kbase_platform_rk_set_opp_info(struct kbase_device *kbdev); +int kbase_platform_rk_init_opp_table(struct kbase_device *kbdev); diff --git a/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c b/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c index 402e984b5dd6..3b223a44a44c 100644 --- a/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c +++ b/drivers/gpu/arm/midgard/platform/rk/mali_kbase_config_rk.c @@ -430,24 +430,8 @@ static void kbase_platform_rk_remove_sysfs_files(struct device *dev) device_remove_file(dev, &dev_attr_utilisation); } -void kbase_platform_rk_set_opp_info(struct kbase_device *kbdev) +int kbase_platform_rk_init_opp_table(struct kbase_device *kbdev) { -#define MAX_PROP_NAME_LEN 3 - char name[MAX_PROP_NAME_LEN]; - int lkg_volt_sel, pvtm_volt_sel, volt_sel; - int err = 0; - - if (!kbdev) - return; - - lkg_volt_sel = rockchip_of_get_lkg_volt_sel(kbdev->dev, "gpu_leakage"); - pvtm_volt_sel = rockchip_of_get_pvtm_volt_sel(kbdev->dev, NULL, "mali"); - - volt_sel = max(lkg_volt_sel, pvtm_volt_sel); - if (volt_sel >= 0) { - snprintf(name, MAX_PROP_NAME_LEN, "L%d", volt_sel); - err = dev_pm_opp_set_prop_name(kbdev->dev, name); - if (err) - dev_err(kbdev->dev, "Failed to set prop name\n"); - } + return rockchip_init_opp_table(kbdev->dev, NULL, + "gpu_leakage", "mali"); } diff --git a/drivers/soc/rockchip/rockchip_opp_select.c b/drivers/soc/rockchip/rockchip_opp_select.c index 8bf81739ceea..88e746b687a5 100644 --- a/drivers/soc/rockchip/rockchip_opp_select.c +++ b/drivers/soc/rockchip/rockchip_opp_select.c @@ -16,15 +16,21 @@ #include "../../clk/rockchip/clk.h" #include "../../base/power/opp/opp.h" -#define LEAKAGE_TABLE_END ~1 +#define MAX_PROP_NAME_LEN 6 +#define SEL_TABLE_END ~1 #define LEAKAGE_INVALID 0xff -struct volt_sel_table { +struct sel_table { int min; int max; int sel; }; +struct bin_sel_table { + int bin; + int sel; +}; + struct pvtm_config { unsigned int freq; unsigned int volt; @@ -42,8 +48,8 @@ struct pvtm_config { #define PVTM_SUB_CH_MAX 8 static int pvtm_value[PVTM_CH_MAX][PVTM_SUB_CH_MAX]; -static int rockchip_get_efuse_value(struct device_node *np, char *porp_name, - int *value) +int rockchip_get_efuse_value(struct device_node *np, char *porp_name, + int *value) { struct nvmem_cell *cell; unsigned char *buf; @@ -69,11 +75,12 @@ static int rockchip_get_efuse_value(struct device_node *np, char *porp_name, return 0; } +EXPORT_SYMBOL(rockchip_get_efuse_value); -static int rockchip_get_volt_sel_table(struct device_node *np, char *porp_name, - struct volt_sel_table **table) +static int rockchip_get_sel_table(struct device_node *np, char *porp_name, + struct sel_table **table) { - struct volt_sel_table *sel_table; + struct sel_table *sel_table; const struct property *prop; int count, i; @@ -105,32 +112,95 @@ static int rockchip_get_volt_sel_table(struct device_node *np, char *porp_name, } sel_table[i].min = 0; sel_table[i].max = 0; - sel_table[i].sel = LEAKAGE_TABLE_END; + sel_table[i].sel = SEL_TABLE_END; *table = sel_table; return 0; } -static int rockchip_get_volt_sel(struct device_node *np, char *name, - int value, int *sel) +static int rockchip_get_bin_sel_table(struct device_node *np, char *porp_name, + struct bin_sel_table **table) { - struct volt_sel_table *table; - int i, j = -1, ret; + struct bin_sel_table *sel_table; + const struct property *prop; + int count, i; - ret = rockchip_get_volt_sel_table(np, name, &table); - if (ret) + prop = of_find_property(np, porp_name, NULL); + if (!prop) + return -EINVAL; + + if (!prop->value) + return -ENODATA; + + count = of_property_count_u32_elems(np, porp_name); + if (count < 0) + return -EINVAL; + + if (count % 2) return -EINVAL; - for (i = 0; table[i].sel != LEAKAGE_TABLE_END; i++) { - if (value >= table[i].min) - j = i; + sel_table = kzalloc(sizeof(*sel_table) * (count / 2 + 1), GFP_KERNEL); + if (!sel_table) + return -ENOMEM; + + for (i = 0; i < count / 2; i++) { + of_property_read_u32_index(np, porp_name, 2 * i, + &sel_table[i].bin); + of_property_read_u32_index(np, porp_name, 2 * i + 1, + &sel_table[i].sel); } - if (j != -1) - *sel = table[j].sel; - else - ret = -EINVAL; + sel_table[i].bin = 0; + sel_table[i].sel = SEL_TABLE_END; + + *table = sel_table; + + return 0; +} + +static int rockchip_get_sel(struct device_node *np, char *name, + int value, int *sel) +{ + struct sel_table *table = NULL; + int i, ret = -EINVAL; + + if (!sel) + return -EINVAL; + + if (rockchip_get_sel_table(np, name, &table)) + return -EINVAL; + + for (i = 0; table[i].sel != SEL_TABLE_END; i++) { + if (value >= table[i].min) { + *sel = table[i].sel; + ret = 0; + } + } + kfree(table); + + return ret; +} + +static int rockchip_get_bin_sel(struct device_node *np, char *name, + int value, int *sel) +{ + struct bin_sel_table *table = NULL; + int i, ret = -EINVAL; + + if (!sel) + return -EINVAL; + + if (rockchip_get_bin_sel_table(np, name, &table)) + return -EINVAL; + + for (i = 0; table[i].sel != SEL_TABLE_END; i++) { + if (value == table[i].bin) { + *sel = table[i].sel; + ret = 0; + break; + } + } kfree(table); return ret; @@ -147,7 +217,7 @@ static int rockchip_parse_pvtm_config(struct device_node *np, return -EINVAL; if (of_property_read_u32_array(np, "rockchip,pvtm-ch", pvtm->ch, 2)) return -EINVAL; - if (pvtm->ch[0] > PVTM_CH_MAX || pvtm->ch[1] > PVTM_SUB_CH_MAX) + if (pvtm->ch[0] >= PVTM_CH_MAX || pvtm->ch[1] >= PVTM_SUB_CH_MAX) return -EINVAL; if (of_property_read_u32(np, "rockchip,pvtm-sample-time", &pvtm->sample_time)) @@ -190,7 +260,7 @@ static int rockchip_get_pvtm_specific_value(struct device *dev, if (of_property_read_u32_array(np, "rockchip,pvtm-ch", ch, 2)) return -EINVAL; - if (ch[0] > PVTM_CH_MAX || ch[1] > PVTM_SUB_CH_MAX) + if (ch[0] >= PVTM_CH_MAX || ch[1] >= PVTM_SUB_CH_MAX) return -EINVAL; if (pvtm_value[ch[0]][ch[1]]) { @@ -273,134 +343,243 @@ pvtm_value_out: return ret; } -int rockchip_of_get_lkg_scale_sel(struct device *dev, char *name) +void rockchip_of_get_lkg_sel(struct device *dev, struct device_node *np, + char *lkg_name, int process, + int *volt_sel, int *scale_sel) { - struct device_node *np; - int leakage, volt_sel; - int ret; + struct property *prop = NULL; + struct nvmem_cell *cell; + int leakage = -EINVAL, ret; + char name[NAME_MAX]; - np = of_parse_phandle(dev->of_node, "operating-points-v2", 0); - if (!np) { - dev_warn(dev, "OPP-v2 not supported\n"); - return -ENOENT; + cell = of_nvmem_cell_get(np, "leakage"); + if (IS_ERR(cell)) { + ret = rockchip_get_efuse_value(np, lkg_name, &leakage); + } else { + nvmem_cell_put(cell); + ret = rockchip_get_efuse_value(np, "leakage", &leakage); + } + if (ret) { + dev_err(dev, "Failed to get leakage\n"); + return; } + dev_info(dev, "leakage=%d\n", leakage); + + if (!volt_sel) + goto next; + if (process >= 0) { + snprintf(name, sizeof(name), + "rockchip,p%d-leakage-voltage-sel", process); + prop = of_find_property(np, name, NULL); + } + if (!prop) + sprintf(name, "rockchip,leakage-voltage-sel"); + ret = rockchip_get_sel(np, name, leakage, volt_sel); + if (!ret) + dev_info(dev, "leakage-volt-sel=%d\n", *volt_sel); + +next: + if (!scale_sel) + return; + if (process >= 0) { + snprintf(name, sizeof(name), + "rockchip,p%d-leakage-scaling-sel", process); + prop = of_find_property(np, name, NULL); + } + if (!prop) + sprintf(name, "rockchip,leakage-scaling-sel"); + ret = rockchip_get_sel(np, name, leakage, scale_sel); + if (!ret) + dev_info(dev, "leakage-scale=%d\n", *scale_sel); +} +EXPORT_SYMBOL(rockchip_of_get_lkg_sel); - ret = rockchip_get_efuse_value(np, name, &leakage); - if (!ret) { - dev_info(dev, "%s=%d\n", name, leakage); - ret = rockchip_get_volt_sel(np, "rockchip,leakage-scaling-sel", - leakage, &volt_sel); - if (!ret) { - dev_info(dev, "%s-scale-sel=%d\n", name, volt_sel); - return volt_sel; - } - } else { - dev_info(dev, "get %s fail\n", name); - ret = rockchip_get_volt_sel(np, "rockchip,leakage-scaling-sel", - 0, &volt_sel); - if (!ret) { - dev_info(dev, "%s-scale-sel=%d\n", name, volt_sel); - return volt_sel; - } +void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np, + char *reg_name, int process, + int *volt_sel, int *scale_sel) +{ + struct property *prop = NULL; + struct regulator *reg; + struct clk *clk; + int pvtm = -EINVAL, ret; + char name[NAME_MAX]; + + clk = clk_get(dev, NULL); + if (IS_ERR_OR_NULL(clk)) { + dev_warn(dev, "Failed to get clk\n"); + return; } - return ret; + reg = regulator_get_optional(dev, reg_name); + if (IS_ERR_OR_NULL(reg)) { + dev_warn(dev, "Failed to get reg\n"); + goto clk_err; + } + + ret = rockchip_get_pvtm_specific_value(dev, np, clk, reg, &pvtm); + if (ret) { + dev_err(dev, "Failed to get pvtm\n"); + goto out; + } + + if (!volt_sel) + goto next; + if (process >= 0) { + snprintf(name, sizeof(name), + "rockchip,p%d-pvtm-voltage-sel", process); + prop = of_find_property(np, name, NULL); + } + if (!prop) + sprintf(name, "rockchip,pvtm-voltage-sel"); + ret = rockchip_get_sel(np, name, pvtm, volt_sel); + if (!ret && volt_sel) + dev_info(dev, "pvtm-volt-sel=%d\n", *volt_sel); + +next: + if (!scale_sel) + goto out; + if (process >= 0) { + snprintf(name, sizeof(name), + "rockchip,p%d-pvtm-scaling-sel", process); + prop = of_find_property(np, name, NULL); + } + if (!prop) + sprintf(name, "rockchip,pvtm-scaling-sel"); + ret = rockchip_get_sel(np, name, pvtm, scale_sel); + if (!ret) + dev_info(dev, "pvtm-scale=%d\n", *scale_sel); + +out: + regulator_put(reg); +clk_err: + clk_put(clk); +} +EXPORT_SYMBOL(rockchip_of_get_pvtm_sel); + +void rockchip_of_get_bin_sel(struct device *dev, struct device_node *np, + int bin, int *scale_sel) +{ + int ret = 0; + + if (!scale_sel || bin < 0) + return; + + ret = rockchip_get_bin_sel(np, "rockchip,bin-scaling-sel", + bin, scale_sel); + if (!ret) + dev_info(dev, "bin-scale=%d\n", *scale_sel); } -EXPORT_SYMBOL(rockchip_of_get_lkg_scale_sel); +EXPORT_SYMBOL(rockchip_of_get_bin_sel); -int rockchip_of_get_lkg_volt_sel(struct device *dev, char *name) +void rockchip_get_soc_info(struct device *dev, + const struct of_device_id *matches, + int *bin, int *process) { + const struct of_device_id *match; struct device_node *np; - int leakage, volt_sel; - int ret; + struct device_node *node; + int (*get_soc_info)(struct device *dev, struct device_node *np, + int *bin, int *process); + int ret = 0; + + if (!matches) + return; np = of_parse_phandle(dev->of_node, "operating-points-v2", 0); if (!np) { dev_warn(dev, "OPP-v2 not supported\n"); - return -ENOENT; + return; } - ret = rockchip_get_efuse_value(np, name, &leakage); - if (!ret) { - dev_info(dev, "%s=%d\n", name, leakage); - ret = rockchip_get_volt_sel(np, "rockchip,leakage-voltage-sel", - leakage, &volt_sel); - if (!ret) { - dev_info(dev, "%s-volt-sel=%d\n", name, volt_sel); - return volt_sel; - } + node = of_find_node_by_path("/"); + match = of_match_node(matches, node); + if (match && match->data) { + get_soc_info = match->data; + ret = get_soc_info(dev, np, bin, process); + if (ret) + dev_err(dev, "Failed to get soc info\n"); } - return ret; + of_node_put(node); + of_node_put(np); } -EXPORT_SYMBOL(rockchip_of_get_lkg_volt_sel); +EXPORT_SYMBOL(rockchip_get_soc_info); -int rockchip_of_get_pvtm_volt_sel(struct device *dev, - char *clk_name, - char *reg_name) +void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name, + char *reg_name, int bin, int process, + int *scale, int *volt_sel) { struct device_node *np; - struct regulator *reg; - struct clk *clk; - int pvtm, volt_sel; - int ret; + int lkg_scale = 0, pvtm_scale = 0, bin_scale = 0; + int lkg_volt_sel = -EINVAL, pvtm_volt_sel = -EINVAL; np = of_parse_phandle(dev->of_node, "operating-points-v2", 0); if (!np) { dev_warn(dev, "OPP-v2 not supported\n"); - return -ENOENT; + return; } - clk = clk_get(dev, clk_name); - if (IS_ERR_OR_NULL(clk)) { - dev_err(dev, "Failed to get clk\n"); - return PTR_ERR(clk); - } + rockchip_of_get_lkg_sel(dev, np, lkg_name, process, + &lkg_volt_sel, &lkg_scale); + rockchip_of_get_pvtm_sel(dev, np, reg_name, process, + &pvtm_volt_sel, &pvtm_scale); + rockchip_of_get_bin_sel(dev, np, bin, &bin_scale); + if (scale) + *scale = max3(lkg_scale, pvtm_scale, bin_scale); + if (volt_sel) + *volt_sel = max(lkg_volt_sel, pvtm_volt_sel); - reg = regulator_get_optional(dev, reg_name); - if (IS_ERR_OR_NULL(reg)) { - dev_err(dev, "Failed to get reg\n"); - clk_put(clk); - return PTR_ERR(reg); - } + of_node_put(np); +} +EXPORT_SYMBOL(rockchip_get_scale_volt_sel); - ret = rockchip_get_pvtm_specific_value(dev, np, clk, reg, &pvtm); - if (!ret) - ret = rockchip_get_volt_sel(np, "rockchip,pvtm-voltage-sel", - pvtm, &volt_sel); +int rockchip_set_opp_info(struct device *dev, int process, int volt_sel) +{ + int ret = 0; + char name[MAX_PROP_NAME_LEN]; - regulator_put(reg); - clk_put(clk); + if (process >= 0) { + if (volt_sel >= 0) + snprintf(name, MAX_PROP_NAME_LEN, "P%d-L%d", + process, volt_sel); + else + snprintf(name, MAX_PROP_NAME_LEN, "P%d", process); + } else if (volt_sel >= 0) { + snprintf(name, MAX_PROP_NAME_LEN, "L%d", volt_sel); + } else { + return 0; + } + + ret = dev_pm_opp_set_prop_name(dev, name); + if (ret) + dev_err(dev, "Failed to set prop name\n"); - return ret ? ret : volt_sel; + return ret; } -EXPORT_SYMBOL(rockchip_of_get_pvtm_volt_sel); +EXPORT_SYMBOL(rockchip_set_opp_info); static int rockchip_of_get_irdrop(struct device_node *np, unsigned long rate) { int irdrop, ret; - ret = rockchip_get_volt_sel(np, "rockchip,board-irdrop", - rate / 1000000, &irdrop); + ret = rockchip_get_sel(np, "rockchip,board-irdrop", rate / 1000000, + &irdrop); return ret ? ret : irdrop; } -int rockchip_adjust_opp_by_irdrop(struct device *dev) +static int rockchip_adjust_opp_by_irdrop(struct device *dev, + struct device_node *np, + int *irdrop_scale, + int *opp_scale) { struct dev_pm_opp *opp, *safe_opp = NULL; - struct device_node *np; + struct clk *clk; unsigned long rate; u32 max_volt = UINT_MAX; int evb_irdrop = 0, board_irdrop, delta_irdrop; int i, count, ret = 0; bool reach_max_volt = false; - np = of_parse_phandle(dev->of_node, "operating-points-v2", 0); - if (!np) { - dev_warn(dev, "OPP-v2 not supported\n"); - return -ENOENT; - } - of_property_read_u32_index(np, "rockchip,max-volt", 0, &max_volt); of_property_read_u32_index(np, "rockchip,evb-irdrop", 0, &evb_irdrop); @@ -441,19 +620,159 @@ int rockchip_adjust_opp_by_irdrop(struct device *dev) } } - if (safe_opp && safe_opp != opp) { - struct clk *clk = of_clk_get_by_name(np, NULL); + clk = of_clk_get_by_name(np, NULL); + if (IS_ERR(clk)) + goto out; + if (safe_opp && safe_opp != opp && irdrop_scale) { + *irdrop_scale = rockchip_pll_clk_rate_to_scale(clk, + safe_opp->rate); + dev_info(dev, "irdrop-scale=%d\n", *irdrop_scale); + } + if (opp_scale) + *opp_scale = rockchip_pll_clk_rate_to_scale(clk, opp->rate); + clk_put(clk); + +out: +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) + rcu_read_unlock(); +#endif + return ret; +} + +static int rockchip_adjust_opp_table(struct device *dev, + unsigned long scale_rate) +{ + struct dev_pm_opp *opp; + unsigned long rate; + int i, count, ret = 0; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) + rcu_read_lock(); +#endif + count = dev_pm_opp_get_opp_count(dev); + if (count <= 0) { + ret = count ? count : -ENODATA; + goto out; + } - if (!IS_ERR(clk)) { - rockchip_pll_clk_adaptive_rate(clk, safe_opp->rate); - clk_put(clk); + for (i = 0, rate = 0; i < count; i++, rate++) { + /* find next rate */ + opp = dev_pm_opp_find_freq_ceil(dev, &rate); + if (IS_ERR(opp)) { + ret = PTR_ERR(opp); + goto out; } + if (opp->rate > scale_rate) + dev_pm_opp_remove(dev, opp->rate); } out: #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) rcu_read_unlock(); #endif - of_node_put(np); return ret; } -EXPORT_SYMBOL(rockchip_adjust_opp_by_irdrop); + +int rockchip_adjust_power_scale(struct device *dev, int scale) +{ + struct device_node *np; + struct clk *clk; + int irdrop_scale = 0, opp_scale = 0; + u32 target_scale, avs_enable = 0, avs_scale = 0; + long scale_rate = 0; + int ret = 0; + + np = of_parse_phandle(dev->of_node, "operating-points-v2", 0); + if (!np) { + dev_warn(dev, "OPP-v2 not supported\n"); + return -ENOENT; + } + of_property_read_u32(np, "rockchip,avs-enable", &avs_enable); + of_property_read_u32(np, "rockchip,avs-scale", &avs_scale); + + rockchip_adjust_opp_by_irdrop(dev, np, &irdrop_scale, &opp_scale); + target_scale = max(irdrop_scale, scale); + if (target_scale <= 0) + return 0; + dev_info(dev, "target-scale=%d\n", target_scale); + + clk = of_clk_get_by_name(np, NULL); + if (IS_ERR(clk)) { + dev_err(dev, "Failed to get opp clk\n"); + goto np_err; + } + + if (avs_enable) { + ret = rockchip_pll_clk_adaptive_scaling(clk, target_scale); + if (ret) + dev_err(dev, "Failed to adaptive scaling\n"); + if (opp_scale < avs_scale) { + dev_info(dev, "avs-scale=%d, opp-scale=%d\n", + avs_scale, opp_scale); + scale_rate = rockchip_pll_clk_scale_to_rate(clk, + avs_scale); + if (scale_rate <= 0) { + dev_err(dev, + "Failed to get avs scale rate, %d\n", + avs_scale); + goto clk_err; + } + dev_info(dev, "avs scale_rate=%lu\n", scale_rate); + ret = rockchip_adjust_opp_table(dev, scale_rate); + if (ret) + dev_err(dev, "Failed to adjust opp table\n"); + } + } else { + if (opp_scale >= target_scale) + goto clk_err; + scale_rate = rockchip_pll_clk_scale_to_rate(clk, target_scale); + if (scale_rate <= 0) { + dev_err(dev, "Failed to get scale rate, %d\n", + target_scale); + goto clk_err; + } + dev_info(dev, "scale_rate=%lu\n", scale_rate); + ret = rockchip_adjust_opp_table(dev, scale_rate); + if (ret) + dev_err(dev, "Failed to adjust opp table\n"); + } + +clk_err: + clk_put(clk); +np_err: + of_node_put(np); + + return 0; +} +EXPORT_SYMBOL(rockchip_adjust_power_scale); + +int rockchip_init_opp_table(struct device *dev, + const struct of_device_id *matches, + char *lkg_name, char *reg_name) +{ + struct device_node *np; + int bin = -EINVAL, process = -EINVAL; + int scale = 0, volt_sel = -EINVAL; + int ret = 0; + + /* Get OPP descriptor node */ + np = _of_get_opp_desc_node(dev); + if (!np) { + dev_dbg(dev, "Failed to find operating-points-v2\n"); + return -ENOENT; + } + of_node_put(np); + + rockchip_get_soc_info(dev, NULL, &bin, &process); + rockchip_get_scale_volt_sel(dev, lkg_name, reg_name, bin, process, + &scale, &volt_sel); + rockchip_set_opp_info(dev, process, volt_sel); + ret = dev_pm_opp_of_add_table(dev); + if (ret) { + dev_err(dev, "Invalid operating-points in device tree.\n"); + return ret; + } + rockchip_adjust_power_scale(dev, scale); + + return 0; +} +EXPORT_SYMBOL(rockchip_init_opp_table); diff --git a/drivers/video/rockchip/vcodec/vcodec_service.c b/drivers/video/rockchip/vcodec/vcodec_service.c index 3036bdc0ab79..e18693586972 100644 --- a/drivers/video/rockchip/vcodec/vcodec_service.c +++ b/drivers/video/rockchip/vcodec/vcodec_service.c @@ -3289,9 +3289,6 @@ static int vcodec_probe(struct platform_device *pdev) struct devfreq_dev_status *stat; struct vpu_service_info *pservice = NULL; struct vpu_session *session = NULL; -#define MAX_PROP_NAME_LEN 3 - char name[MAX_PROP_NAME_LEN]; - int lkg_volt_sel; pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info), GFP_KERNEL); @@ -3385,21 +3382,12 @@ static int vcodec_probe(struct platform_device *pdev) goto err; if (!IS_ERR(pservice->vdd_vcodec)) { - lkg_volt_sel = rockchip_of_get_lkg_volt_sel(dev, - "rkvdec_leakage"); - if (lkg_volt_sel >= 0) { - snprintf(name, MAX_PROP_NAME_LEN, "L%d", lkg_volt_sel); - ret = dev_pm_opp_set_prop_name(dev, name); - if (ret) - dev_err(dev, "Failed to set prop name\n"); - } - - if (dev_pm_opp_of_add_table(dev)) { - dev_err(dev, "Invalid operating-points\n"); - ret = -EINVAL; - goto err; + ret = rockchip_init_opp_table(dev, NULL, + "rkvdec_leakage", "vcodec"); + if (ret) { + dev_err(dev, "Failed to init_opp_table (%d)\n", ret); + return ret; } - pservice->devfreq = devm_devfreq_add_device(dev, devp, "userspace", NULL); if (IS_ERR(pservice->devfreq)) { diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index c39c964bbaed..e1eb0967feef 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -697,11 +697,17 @@ unsigned long cpufreq_scale_freq_capacity(struct sched_domain *sd, int cpu); unsigned long cpufreq_scale_max_freq_capacity(int cpu); #ifdef CONFIG_ARM_ROCKCHIP_CPUFREQ unsigned int rockchip_cpufreq_adjust_target(int cpu, unsigned int freq); +int rockchip_cpufreq_get_scale(int cpu); #else static inline unsigned int rockchip_cpufreq_adjust_target(int cpu, unsigned int freq) { return freq; } + +int rockchip_cpufreq_get_scale(int cpu) +{ + return -EINVAL; +} #endif #endif /* _LINUX_CPUFREQ_H */ diff --git a/include/soc/rockchip/rockchip_opp_select.h b/include/soc/rockchip/rockchip_opp_select.h index b4317d030bd9..5d3d37b442ea 100644 --- a/include/soc/rockchip/rockchip_opp_select.h +++ b/include/soc/rockchip/rockchip_opp_select.h @@ -6,11 +6,26 @@ #ifndef __SOC_ROCKCHIP_OPP_SELECT_H #define __SOC_ROCKCHIP_OPP_SELECT_H -int rockchip_of_get_lkg_scale_sel(struct device *dev, char *name); -int rockchip_of_get_lkg_volt_sel(struct device *dev, char *name); -int rockchip_of_get_pvtm_volt_sel(struct device *dev, - char *clk_name, - char *reg_name); -int rockchip_adjust_opp_by_irdrop(struct device *dev); +void rockchip_of_get_lkg_sel(struct device *dev, struct device_node *np, + char *lkg_name, int process, + int *volt_sel, int *scale_sel); +void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np, + char *reg_name, int process, + int *volt_sel, int *scale_sel); +void rockchip_of_get_bin_sel(struct device *dev, struct device_node *np, + int bin, int *scale_sel); +int rockchip_get_efuse_value(struct device_node *np, char *porp_name, + int *value); +void rockchip_get_soc_info(struct device *dev, + const struct of_device_id *matches, + int *bin, int *process); +void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name, + char *reg_name, int bin, int process, + int *scale, int *volt_sel); +int rockchip_set_opp_info(struct device *dev, int process, int volt_sel); +int rockchip_adjust_power_scale(struct device *dev, int scale); +int rockchip_init_opp_table(struct device *dev, + const struct of_device_id *matches, + char *lkg_name, char *reg_name); #endif |