Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pmdomain: core: Set the required dev for a required OPP during genpd attach

In the single PM domain case there is no need for platform code to specify
the index of the corresponding required OPP in DT, as the index must be
zero. This allows us to assign a required dev for the required OPP from
genpd, while attaching a device to its PM domain.

In this way, we can remove some of the genpd specific code in the OPP core
for the single PM domain case. Although, this cleanup is made from a
subsequent change.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Link: https://lore.kernel.org/r/20241002122232.194245-7-ulf.hansson@linaro.org

+40 -3
+39 -3
drivers/pmdomain/core.c
··· 1722 1722 1723 1723 spin_unlock_irq(&dev->power.lock); 1724 1724 1725 + dev_pm_opp_clear_config(gpd_data->opp_token); 1725 1726 kfree(gpd_data->td); 1726 1727 kfree(gpd_data); 1727 1728 dev_pm_put_subsys_data(dev); ··· 2885 2884 genpd_queue_power_off_work(pd); 2886 2885 } 2887 2886 2887 + static int genpd_set_required_opp_dev(struct device *dev, 2888 + struct device *base_dev) 2889 + { 2890 + struct dev_pm_opp_config config = { 2891 + .required_dev = dev, 2892 + }; 2893 + int ret; 2894 + 2895 + /* Limit support to non-providers for now. */ 2896 + if (of_property_present(base_dev->of_node, "#power-domain-cells")) 2897 + return 0; 2898 + 2899 + if (!dev_pm_opp_of_has_required_opp(base_dev)) 2900 + return 0; 2901 + 2902 + ret = dev_pm_opp_set_config(base_dev, &config); 2903 + if (ret < 0) 2904 + return ret; 2905 + 2906 + dev_gpd_data(dev)->opp_token = ret; 2907 + return 0; 2908 + } 2909 + 2888 2910 static int genpd_set_required_opp(struct device *dev, unsigned int index) 2889 2911 { 2890 2912 int ret, pstate; ··· 2932 2908 } 2933 2909 2934 2910 static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev, 2935 - unsigned int index, bool power_on) 2911 + unsigned int index, unsigned int num_domains, 2912 + bool power_on) 2936 2913 { 2937 2914 struct of_phandle_args pd_args; 2938 2915 struct generic_pm_domain *pd; ··· 2964 2939 2965 2940 dev->pm_domain->detach = genpd_dev_pm_detach; 2966 2941 dev->pm_domain->sync = genpd_dev_pm_sync; 2942 + 2943 + /* 2944 + * For a single PM domain the index of the required OPP must be zero, so 2945 + * let's try to assign a required dev in that case. In the multiple PM 2946 + * domains case, we need platform code to specify the index. 2947 + */ 2948 + if (num_domains == 1) { 2949 + ret = genpd_set_required_opp_dev(dev, base_dev); 2950 + if (ret) 2951 + goto err; 2952 + } 2967 2953 2968 2954 ret = genpd_set_required_opp(dev, index); 2969 2955 if (ret) ··· 3030 2994 "#power-domain-cells") != 1) 3031 2995 return 0; 3032 2996 3033 - return __genpd_dev_pm_attach(dev, dev, 0, true); 2997 + return __genpd_dev_pm_attach(dev, dev, 0, 1, true); 3034 2998 } 3035 2999 EXPORT_SYMBOL_GPL(genpd_dev_pm_attach); 3036 3000 ··· 3083 3047 } 3084 3048 3085 3049 /* Try to attach the device to the PM domain at the specified index. */ 3086 - ret = __genpd_dev_pm_attach(virt_dev, dev, index, false); 3050 + ret = __genpd_dev_pm_attach(virt_dev, dev, index, num_domains, false); 3087 3051 if (ret < 1) { 3088 3052 device_unregister(virt_dev); 3089 3053 return ret ? ERR_PTR(ret) : NULL;
+1
include/linux/pm_domain.h
··· 252 252 unsigned int performance_state; 253 253 unsigned int default_pstate; 254 254 unsigned int rpm_pstate; 255 + unsigned int opp_token; 255 256 bool hw_mode; 256 257 void *data; 257 258 };