OPP updates for 5.20-rc1
- Make dev_pm_opp_set_regulators() accept NULL terminated list (Viresh Kumar). - Add dev_pm_opp_set_config() and friends and migrate other users/helpers to using them (Viresh Kumar). - Add support for multiple clocks for a device (Viresh Kumar and Krzysztof Kozlowski). - Configure resources before adding OPP table for Venus (Stanimir Varbanov). - Keep reference count up for opp->np and opp_table->np while they are still in use (Liang He). - Minor cleanups (Viresh Kumar and Yang Li). -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEx73Crsp7f6M6scA70rkcPK6BEhwFAmLoprIACgkQ0rkcPK6B Ehz2nBAApgYUDGkEjWcJufIxW1mH77uonzmWUV2jQBEcCvYnjdwhJ0RpQUT75Xnk hTYJ5v9UKwOVl+puPguUe7UzSmWcsI9AzJCj0Vr/LBiln+sawoI51lqOaNjCJkmZ VytQJB23DNsYJAG/0xM42+syu+IONJ4vCP/9m35sWlevfFihbfQsEK+iEKsseVgd sEwPvHyixLWyeaoAf+6apOBP2Lf+/3R8h6Iv0U8n8jOzUpQQ5r/RSDyZeARP7gze 64aXvsvr7D0Mc9GpevDJKGtPFbRNfq5I4Lg5MOZ8NQVjXOqlWJil3oYEnKQxIH0Y EEzcrSuWi3SEeHrQfj+GFs/D7z2ZHqmbg7yb4P7zSeqLvG+7Ey9aYOXOg5LykrYk 1rZQzenLMF91RnhdRLI22SJngokOYZjWBFp62mPqmEYtx2VsYQlxqGtJoCHYDRx3 QRp0ZYJBnHQMt7saiIRFdAAIz7/G5lkiUplVzqAWe7AEpUG3Y7kvIqfwi69s3I5S ERSf3qqx3dUGFXYoxwglEwaf8ZvKQnPOzOLmbyc9Hrj2MclfKf9vW+0/4J6iiDlu ITpsqEWUhtEjwCt3lbM6PWNRrCJHi6YkKw0sORxEWR639cqckmk6ZAuaRPeOob6a nZ/UvwU2LMRG1zZyrsB3bbUkijJ019RPySmjCXApLsoNT1qpUr0= =NHBQ -----END PGP SIGNATURE----- Merge tag 'opp-updates-5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm Pull operating performance points (OPP) updates for 5.20-rc1 from Viresh Kumar: "- Make dev_pm_opp_set_regulators() accept NULL terminated list (Viresh Kumar). - Add dev_pm_opp_set_config() and friends and migrate other users/helpers to using them (Viresh Kumar). - Add support for multiple clocks for a device (Viresh Kumar and Krzysztof Kozlowski). - Configure resources before adding OPP table for Venus (Stanimir Varbanov). - Keep reference count up for opp->np and opp_table->np while they are still in use (Liang He). - Minor cleanups (Viresh Kumar and Yang Li)." * tag 'opp-updates-5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm: (43 commits) venus: pm_helpers: Fix warning in OPP during probe OPP: Don't drop opp->np reference while it is still in use OPP: Don't drop opp_table->np reference while it is still in use OPP: Remove dev{m}_pm_opp_of_add_table_noclk() PM / devfreq: tegra30: Register config_clks helper OPP: Allow config_clks helper for single clk case OPP: Provide a simple implementation to configure multiple clocks OPP: Assert clk_count == 1 for single clk helpers OPP: Add key specific assert() method to key finding helpers OPP: Compare bandwidths for all paths in _opp_compare_key() OPP: Allow multiple clocks for a device dt-bindings: opp: accept array of frequencies OPP: Make dev_pm_opp_set_opp() independent of frequency OPP: Reuse _opp_compare_key() in _opp_add_static_v2() OPP: Remove rate_not_available parameter to _opp_add() OPP: Use consistent names for OPP table instances OPP: Use generic key finding helpers for bandwidth key OPP: Use generic key finding helpers for level key OPP: Add generic key finding helpers and use them for freq APIs OPP: Remove dev_pm_opp_find_freq_ceil_by_volt() ...
This commit is contained in:
commit
f6e0b468da
@ -50,6 +50,16 @@ patternProperties:
|
|||||||
property to uniquely identify the OPP nodes exists. Devices like power
|
property to uniquely identify the OPP nodes exists. Devices like power
|
||||||
domains must have another (implementation dependent) property.
|
domains must have another (implementation dependent) property.
|
||||||
|
|
||||||
|
Entries for multiple clocks shall be provided in the same field, as
|
||||||
|
array of frequencies. The OPP binding doesn't provide any provisions
|
||||||
|
to relate the values to their clocks or the order in which the clocks
|
||||||
|
need to be configured and that is left for the implementation
|
||||||
|
specific binding.
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 16
|
||||||
|
items:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
opp-microvolt:
|
opp-microvolt:
|
||||||
description: |
|
description: |
|
||||||
Voltage for the OPP
|
Voltage for the OPP
|
||||||
|
@ -29,9 +29,9 @@ struct private_data {
|
|||||||
|
|
||||||
cpumask_var_t cpus;
|
cpumask_var_t cpus;
|
||||||
struct device *cpu_dev;
|
struct device *cpu_dev;
|
||||||
struct opp_table *opp_table;
|
|
||||||
struct cpufreq_frequency_table *freq_table;
|
struct cpufreq_frequency_table *freq_table;
|
||||||
bool have_static_opps;
|
bool have_static_opps;
|
||||||
|
int opp_token;
|
||||||
};
|
};
|
||||||
|
|
||||||
static LIST_HEAD(priv_list);
|
static LIST_HEAD(priv_list);
|
||||||
@ -193,7 +193,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
|
|||||||
struct private_data *priv;
|
struct private_data *priv;
|
||||||
struct device *cpu_dev;
|
struct device *cpu_dev;
|
||||||
bool fallback = false;
|
bool fallback = false;
|
||||||
const char *reg_name;
|
const char *reg_name[] = { NULL, NULL };
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Check if this CPU is already covered by some other policy */
|
/* Check if this CPU is already covered by some other policy */
|
||||||
@ -218,12 +218,11 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
|
|||||||
* OPP layer will be taking care of regulators now, but it needs to know
|
* OPP layer will be taking care of regulators now, but it needs to know
|
||||||
* the name of the regulator first.
|
* the name of the regulator first.
|
||||||
*/
|
*/
|
||||||
reg_name = find_supply_name(cpu_dev);
|
reg_name[0] = find_supply_name(cpu_dev);
|
||||||
if (reg_name) {
|
if (reg_name[0]) {
|
||||||
priv->opp_table = dev_pm_opp_set_regulators(cpu_dev, ®_name,
|
priv->opp_token = dev_pm_opp_set_regulators(cpu_dev, reg_name);
|
||||||
1);
|
if (priv->opp_token < 0) {
|
||||||
if (IS_ERR(priv->opp_table)) {
|
ret = priv->opp_token;
|
||||||
ret = PTR_ERR(priv->opp_table);
|
|
||||||
if (ret != -EPROBE_DEFER)
|
if (ret != -EPROBE_DEFER)
|
||||||
dev_err(cpu_dev, "failed to set regulators: %d\n",
|
dev_err(cpu_dev, "failed to set regulators: %d\n",
|
||||||
ret);
|
ret);
|
||||||
@ -295,7 +294,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
|
|||||||
out:
|
out:
|
||||||
if (priv->have_static_opps)
|
if (priv->have_static_opps)
|
||||||
dev_pm_opp_of_cpumask_remove_table(priv->cpus);
|
dev_pm_opp_of_cpumask_remove_table(priv->cpus);
|
||||||
dev_pm_opp_put_regulators(priv->opp_table);
|
dev_pm_opp_put_regulators(priv->opp_token);
|
||||||
free_cpumask:
|
free_cpumask:
|
||||||
free_cpumask_var(priv->cpus);
|
free_cpumask_var(priv->cpus);
|
||||||
return ret;
|
return ret;
|
||||||
@ -309,7 +308,7 @@ static void dt_cpufreq_release(void)
|
|||||||
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &priv->freq_table);
|
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &priv->freq_table);
|
||||||
if (priv->have_static_opps)
|
if (priv->have_static_opps)
|
||||||
dev_pm_opp_of_cpumask_remove_table(priv->cpus);
|
dev_pm_opp_of_cpumask_remove_table(priv->cpus);
|
||||||
dev_pm_opp_put_regulators(priv->opp_table);
|
dev_pm_opp_put_regulators(priv->opp_token);
|
||||||
free_cpumask_var(priv->cpus);
|
free_cpumask_var(priv->cpus);
|
||||||
list_del(&priv->node);
|
list_del(&priv->node);
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@
|
|||||||
|
|
||||||
/* cpufreq-dt device registered by imx-cpufreq-dt */
|
/* cpufreq-dt device registered by imx-cpufreq-dt */
|
||||||
static struct platform_device *cpufreq_dt_pdev;
|
static struct platform_device *cpufreq_dt_pdev;
|
||||||
static struct opp_table *cpufreq_opp_table;
|
|
||||||
static struct device *cpu_dev;
|
static struct device *cpu_dev;
|
||||||
|
static int cpufreq_opp_token;
|
||||||
|
|
||||||
enum IMX7ULP_CPUFREQ_CLKS {
|
enum IMX7ULP_CPUFREQ_CLKS {
|
||||||
ARM,
|
ARM,
|
||||||
@ -153,9 +153,9 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
|
|||||||
dev_info(&pdev->dev, "cpu speed grade %d mkt segment %d supported-hw %#x %#x\n",
|
dev_info(&pdev->dev, "cpu speed grade %d mkt segment %d supported-hw %#x %#x\n",
|
||||||
speed_grade, mkt_segment, supported_hw[0], supported_hw[1]);
|
speed_grade, mkt_segment, supported_hw[0], supported_hw[1]);
|
||||||
|
|
||||||
cpufreq_opp_table = dev_pm_opp_set_supported_hw(cpu_dev, supported_hw, 2);
|
cpufreq_opp_token = dev_pm_opp_set_supported_hw(cpu_dev, supported_hw, 2);
|
||||||
if (IS_ERR(cpufreq_opp_table)) {
|
if (cpufreq_opp_token < 0) {
|
||||||
ret = PTR_ERR(cpufreq_opp_table);
|
ret = cpufreq_opp_token;
|
||||||
dev_err(&pdev->dev, "Failed to set supported opp: %d\n", ret);
|
dev_err(&pdev->dev, "Failed to set supported opp: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -163,7 +163,7 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
|
|||||||
cpufreq_dt_pdev = platform_device_register_data(
|
cpufreq_dt_pdev = platform_device_register_data(
|
||||||
&pdev->dev, "cpufreq-dt", -1, NULL, 0);
|
&pdev->dev, "cpufreq-dt", -1, NULL, 0);
|
||||||
if (IS_ERR(cpufreq_dt_pdev)) {
|
if (IS_ERR(cpufreq_dt_pdev)) {
|
||||||
dev_pm_opp_put_supported_hw(cpufreq_opp_table);
|
dev_pm_opp_put_supported_hw(cpufreq_opp_token);
|
||||||
ret = PTR_ERR(cpufreq_dt_pdev);
|
ret = PTR_ERR(cpufreq_dt_pdev);
|
||||||
dev_err(&pdev->dev, "Failed to register cpufreq-dt: %d\n", ret);
|
dev_err(&pdev->dev, "Failed to register cpufreq-dt: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
@ -176,7 +176,7 @@ static int imx_cpufreq_dt_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
platform_device_unregister(cpufreq_dt_pdev);
|
platform_device_unregister(cpufreq_dt_pdev);
|
||||||
if (!of_machine_is_compatible("fsl,imx7ulp"))
|
if (!of_machine_is_compatible("fsl,imx7ulp"))
|
||||||
dev_pm_opp_put_supported_hw(cpufreq_opp_table);
|
dev_pm_opp_put_supported_hw(cpufreq_opp_token);
|
||||||
else
|
else
|
||||||
clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks);
|
clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks);
|
||||||
|
|
||||||
|
@ -55,9 +55,7 @@ struct qcom_cpufreq_match_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct qcom_cpufreq_drv {
|
struct qcom_cpufreq_drv {
|
||||||
struct opp_table **names_opp_tables;
|
int *opp_tokens;
|
||||||
struct opp_table **hw_opp_tables;
|
|
||||||
struct opp_table **genpd_opp_tables;
|
|
||||||
u32 versions;
|
u32 versions;
|
||||||
const struct qcom_cpufreq_match_data *data;
|
const struct qcom_cpufreq_match_data *data;
|
||||||
};
|
};
|
||||||
@ -315,72 +313,43 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
of_node_put(np);
|
of_node_put(np);
|
||||||
|
|
||||||
drv->names_opp_tables = kcalloc(num_possible_cpus(),
|
drv->opp_tokens = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tokens),
|
||||||
sizeof(*drv->names_opp_tables),
|
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!drv->names_opp_tables) {
|
if (!drv->opp_tokens) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto free_drv;
|
goto free_drv;
|
||||||
}
|
}
|
||||||
drv->hw_opp_tables = kcalloc(num_possible_cpus(),
|
|
||||||
sizeof(*drv->hw_opp_tables),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!drv->hw_opp_tables) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto free_opp_names;
|
|
||||||
}
|
|
||||||
|
|
||||||
drv->genpd_opp_tables = kcalloc(num_possible_cpus(),
|
|
||||||
sizeof(*drv->genpd_opp_tables),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!drv->genpd_opp_tables) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto free_opp;
|
|
||||||
}
|
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.supported_hw = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
cpu_dev = get_cpu_device(cpu);
|
cpu_dev = get_cpu_device(cpu);
|
||||||
if (NULL == cpu_dev) {
|
if (NULL == cpu_dev) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto free_genpd_opp;
|
goto free_opp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drv->data->get_version) {
|
if (drv->data->get_version) {
|
||||||
|
config.supported_hw = &drv->versions;
|
||||||
|
config.supported_hw_count = 1;
|
||||||
|
|
||||||
if (pvs_name) {
|
if (pvs_name)
|
||||||
drv->names_opp_tables[cpu] = dev_pm_opp_set_prop_name(
|
config.prop_name = pvs_name;
|
||||||
cpu_dev,
|
|
||||||
pvs_name);
|
|
||||||
if (IS_ERR(drv->names_opp_tables[cpu])) {
|
|
||||||
ret = PTR_ERR(drv->names_opp_tables[cpu]);
|
|
||||||
dev_err(cpu_dev, "Failed to add OPP name %s\n",
|
|
||||||
pvs_name);
|
|
||||||
goto free_opp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
drv->hw_opp_tables[cpu] = dev_pm_opp_set_supported_hw(
|
|
||||||
cpu_dev, &drv->versions, 1);
|
|
||||||
if (IS_ERR(drv->hw_opp_tables[cpu])) {
|
|
||||||
ret = PTR_ERR(drv->hw_opp_tables[cpu]);
|
|
||||||
dev_err(cpu_dev,
|
|
||||||
"Failed to set supported hardware\n");
|
|
||||||
goto free_genpd_opp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drv->data->genpd_names) {
|
if (drv->data->genpd_names) {
|
||||||
drv->genpd_opp_tables[cpu] =
|
config.genpd_names = drv->data->genpd_names;
|
||||||
dev_pm_opp_attach_genpd(cpu_dev,
|
config.virt_devs = NULL;
|
||||||
drv->data->genpd_names,
|
}
|
||||||
NULL);
|
|
||||||
if (IS_ERR(drv->genpd_opp_tables[cpu])) {
|
if (config.supported_hw || config.genpd_names) {
|
||||||
ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
|
drv->opp_tokens[cpu] = dev_pm_opp_set_config(cpu_dev, &config);
|
||||||
if (ret != -EPROBE_DEFER)
|
if (drv->opp_tokens[cpu] < 0) {
|
||||||
dev_err(cpu_dev,
|
ret = drv->opp_tokens[cpu];
|
||||||
"Could not attach to pm_domain: %d\n",
|
dev_err(cpu_dev, "Failed to set OPP config\n");
|
||||||
ret);
|
goto free_opp;
|
||||||
goto free_genpd_opp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -395,27 +364,10 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
|
|||||||
ret = PTR_ERR(cpufreq_dt_pdev);
|
ret = PTR_ERR(cpufreq_dt_pdev);
|
||||||
dev_err(cpu_dev, "Failed to register platform device\n");
|
dev_err(cpu_dev, "Failed to register platform device\n");
|
||||||
|
|
||||||
free_genpd_opp:
|
|
||||||
for_each_possible_cpu(cpu) {
|
|
||||||
if (IS_ERR(drv->genpd_opp_tables[cpu]))
|
|
||||||
break;
|
|
||||||
dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]);
|
|
||||||
}
|
|
||||||
kfree(drv->genpd_opp_tables);
|
|
||||||
free_opp:
|
free_opp:
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu)
|
||||||
if (IS_ERR(drv->names_opp_tables[cpu]))
|
dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
|
||||||
break;
|
kfree(drv->opp_tokens);
|
||||||
dev_pm_opp_put_prop_name(drv->names_opp_tables[cpu]);
|
|
||||||
}
|
|
||||||
for_each_possible_cpu(cpu) {
|
|
||||||
if (IS_ERR(drv->hw_opp_tables[cpu]))
|
|
||||||
break;
|
|
||||||
dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]);
|
|
||||||
}
|
|
||||||
kfree(drv->hw_opp_tables);
|
|
||||||
free_opp_names:
|
|
||||||
kfree(drv->names_opp_tables);
|
|
||||||
free_drv:
|
free_drv:
|
||||||
kfree(drv);
|
kfree(drv);
|
||||||
|
|
||||||
@ -429,15 +381,10 @@ static int qcom_cpufreq_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
platform_device_unregister(cpufreq_dt_pdev);
|
platform_device_unregister(cpufreq_dt_pdev);
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu)
|
||||||
dev_pm_opp_put_supported_hw(drv->names_opp_tables[cpu]);
|
dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
|
||||||
dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]);
|
|
||||||
dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]);
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(drv->names_opp_tables);
|
kfree(drv->opp_tokens);
|
||||||
kfree(drv->hw_opp_tables);
|
|
||||||
kfree(drv->genpd_opp_tables);
|
|
||||||
kfree(drv);
|
kfree(drv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -156,9 +156,13 @@ static int sti_cpufreq_set_opp_info(void)
|
|||||||
unsigned int hw_info_offset;
|
unsigned int hw_info_offset;
|
||||||
unsigned int version[VERSION_ELEMENTS];
|
unsigned int version[VERSION_ELEMENTS];
|
||||||
int pcode, substrate, major, minor;
|
int pcode, substrate, major, minor;
|
||||||
int ret;
|
int opp_token, ret;
|
||||||
char name[MAX_PCODE_NAME_LEN];
|
char name[MAX_PCODE_NAME_LEN];
|
||||||
struct opp_table *opp_table;
|
struct dev_pm_opp_config config = {
|
||||||
|
.supported_hw = version,
|
||||||
|
.supported_hw_count = ARRAY_SIZE(version),
|
||||||
|
.prop_name = name,
|
||||||
|
};
|
||||||
|
|
||||||
reg_fields = sti_cpufreq_match();
|
reg_fields = sti_cpufreq_match();
|
||||||
if (!reg_fields) {
|
if (!reg_fields) {
|
||||||
@ -210,21 +214,14 @@ use_defaults:
|
|||||||
|
|
||||||
snprintf(name, MAX_PCODE_NAME_LEN, "pcode%d", pcode);
|
snprintf(name, MAX_PCODE_NAME_LEN, "pcode%d", pcode);
|
||||||
|
|
||||||
opp_table = dev_pm_opp_set_prop_name(dev, name);
|
|
||||||
if (IS_ERR(opp_table)) {
|
|
||||||
dev_err(dev, "Failed to set prop name\n");
|
|
||||||
return PTR_ERR(opp_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
version[0] = BIT(major);
|
version[0] = BIT(major);
|
||||||
version[1] = BIT(minor);
|
version[1] = BIT(minor);
|
||||||
version[2] = BIT(substrate);
|
version[2] = BIT(substrate);
|
||||||
|
|
||||||
opp_table = dev_pm_opp_set_supported_hw(dev, version, VERSION_ELEMENTS);
|
opp_token = dev_pm_opp_set_config(dev, &config);
|
||||||
if (IS_ERR(opp_table)) {
|
if (opp_token < 0) {
|
||||||
dev_err(dev, "Failed to set supported hardware\n");
|
dev_err(dev, "Failed to set OPP config\n");
|
||||||
ret = PTR_ERR(opp_table);
|
return opp_token;
|
||||||
goto err_put_prop_name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(dev, "pcode: %d major: %d minor: %d substrate: %d\n",
|
dev_dbg(dev, "pcode: %d major: %d minor: %d substrate: %d\n",
|
||||||
@ -233,10 +230,6 @@ use_defaults:
|
|||||||
version[0], version[1], version[2]);
|
version[0], version[1], version[2]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_put_prop_name:
|
|
||||||
dev_pm_opp_put_prop_name(opp_table);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sti_cpufreq_fetch_syscon_registers(void)
|
static int sti_cpufreq_fetch_syscon_registers(void)
|
||||||
|
@ -86,20 +86,20 @@ static int sun50i_cpufreq_get_efuse(u32 *versions)
|
|||||||
|
|
||||||
static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
|
static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct opp_table **opp_tables;
|
int *opp_tokens;
|
||||||
char name[MAX_NAME_LEN];
|
char name[MAX_NAME_LEN];
|
||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
u32 speed = 0;
|
u32 speed = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables),
|
opp_tokens = kcalloc(num_possible_cpus(), sizeof(*opp_tokens),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!opp_tables)
|
if (!opp_tokens)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = sun50i_cpufreq_get_efuse(&speed);
|
ret = sun50i_cpufreq_get_efuse(&speed);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(opp_tables);
|
kfree(opp_tokens);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,9 +113,9 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
|
|||||||
goto free_opp;
|
goto free_opp;
|
||||||
}
|
}
|
||||||
|
|
||||||
opp_tables[cpu] = dev_pm_opp_set_prop_name(cpu_dev, name);
|
opp_tokens[cpu] = dev_pm_opp_set_prop_name(cpu_dev, name);
|
||||||
if (IS_ERR(opp_tables[cpu])) {
|
if (opp_tokens[cpu] < 0) {
|
||||||
ret = PTR_ERR(opp_tables[cpu]);
|
ret = opp_tokens[cpu];
|
||||||
pr_err("Failed to set prop name\n");
|
pr_err("Failed to set prop name\n");
|
||||||
goto free_opp;
|
goto free_opp;
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
|
|||||||
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
|
cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
if (!IS_ERR(cpufreq_dt_pdev)) {
|
if (!IS_ERR(cpufreq_dt_pdev)) {
|
||||||
platform_set_drvdata(pdev, opp_tables);
|
platform_set_drvdata(pdev, opp_tokens);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,27 +132,24 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
|
|||||||
pr_err("Failed to register platform device\n");
|
pr_err("Failed to register platform device\n");
|
||||||
|
|
||||||
free_opp:
|
free_opp:
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu)
|
||||||
if (IS_ERR_OR_NULL(opp_tables[cpu]))
|
dev_pm_opp_put_prop_name(opp_tokens[cpu]);
|
||||||
break;
|
kfree(opp_tokens);
|
||||||
dev_pm_opp_put_prop_name(opp_tables[cpu]);
|
|
||||||
}
|
|
||||||
kfree(opp_tables);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sun50i_cpufreq_nvmem_remove(struct platform_device *pdev)
|
static int sun50i_cpufreq_nvmem_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct opp_table **opp_tables = platform_get_drvdata(pdev);
|
int *opp_tokens = platform_get_drvdata(pdev);
|
||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
|
|
||||||
platform_device_unregister(cpufreq_dt_pdev);
|
platform_device_unregister(cpufreq_dt_pdev);
|
||||||
|
|
||||||
for_each_possible_cpu(cpu)
|
for_each_possible_cpu(cpu)
|
||||||
dev_pm_opp_put_prop_name(opp_tables[cpu]);
|
dev_pm_opp_put_prop_name(opp_tokens[cpu]);
|
||||||
|
|
||||||
kfree(opp_tables);
|
kfree(opp_tokens);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,9 @@ static bool cpu0_node_has_opp_v2_prop(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra20_cpufreq_put_supported_hw(void *opp_table)
|
static void tegra20_cpufreq_put_supported_hw(void *opp_token)
|
||||||
{
|
{
|
||||||
dev_pm_opp_put_supported_hw(opp_table);
|
dev_pm_opp_put_supported_hw((unsigned long) opp_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra20_cpufreq_dt_unregister(void *cpufreq_dt)
|
static void tegra20_cpufreq_dt_unregister(void *cpufreq_dt)
|
||||||
@ -45,7 +45,6 @@ static void tegra20_cpufreq_dt_unregister(void *cpufreq_dt)
|
|||||||
static int tegra20_cpufreq_probe(struct platform_device *pdev)
|
static int tegra20_cpufreq_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct platform_device *cpufreq_dt;
|
struct platform_device *cpufreq_dt;
|
||||||
struct opp_table *opp_table;
|
|
||||||
struct device *cpu_dev;
|
struct device *cpu_dev;
|
||||||
u32 versions[2];
|
u32 versions[2];
|
||||||
int err;
|
int err;
|
||||||
@ -71,16 +70,15 @@ static int tegra20_cpufreq_probe(struct platform_device *pdev)
|
|||||||
if (WARN_ON(!cpu_dev))
|
if (WARN_ON(!cpu_dev))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
opp_table = dev_pm_opp_set_supported_hw(cpu_dev, versions, 2);
|
err = dev_pm_opp_set_supported_hw(cpu_dev, versions, 2);
|
||||||
err = PTR_ERR_OR_ZERO(opp_table);
|
if (err < 0) {
|
||||||
if (err) {
|
|
||||||
dev_err(&pdev->dev, "failed to set supported hw: %d\n", err);
|
dev_err(&pdev->dev, "failed to set supported hw: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = devm_add_action_or_reset(&pdev->dev,
|
err = devm_add_action_or_reset(&pdev->dev,
|
||||||
tegra20_cpufreq_put_supported_hw,
|
tegra20_cpufreq_put_supported_hw,
|
||||||
opp_table);
|
(void *)((unsigned long) err));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ struct ti_cpufreq_data {
|
|||||||
struct device_node *opp_node;
|
struct device_node *opp_node;
|
||||||
struct regmap *syscon;
|
struct regmap *syscon;
|
||||||
const struct ti_cpufreq_soc_data *soc_data;
|
const struct ti_cpufreq_soc_data *soc_data;
|
||||||
struct opp_table *opp_table;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned long amx3_efuse_xlate(struct ti_cpufreq_data *opp_data,
|
static unsigned long amx3_efuse_xlate(struct ti_cpufreq_data *opp_data,
|
||||||
@ -173,7 +172,7 @@ static struct ti_cpufreq_soc_data omap34xx_soc_data = {
|
|||||||
* seems to always read as 0).
|
* seems to always read as 0).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char * const omap3_reg_names[] = {"cpu0", "vbb"};
|
static const char * const omap3_reg_names[] = {"cpu0", "vbb", NULL};
|
||||||
|
|
||||||
static struct ti_cpufreq_soc_data omap36xx_soc_data = {
|
static struct ti_cpufreq_soc_data omap36xx_soc_data = {
|
||||||
.reg_names = omap3_reg_names,
|
.reg_names = omap3_reg_names,
|
||||||
@ -324,10 +323,13 @@ static int ti_cpufreq_probe(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
u32 version[VERSION_COUNT];
|
u32 version[VERSION_COUNT];
|
||||||
const struct of_device_id *match;
|
const struct of_device_id *match;
|
||||||
struct opp_table *ti_opp_table;
|
|
||||||
struct ti_cpufreq_data *opp_data;
|
struct ti_cpufreq_data *opp_data;
|
||||||
const char * const default_reg_names[] = {"vdd", "vbb"};
|
const char * const default_reg_names[] = {"vdd", "vbb", NULL};
|
||||||
int ret;
|
int ret;
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.supported_hw = version,
|
||||||
|
.supported_hw_count = ARRAY_SIZE(version),
|
||||||
|
};
|
||||||
|
|
||||||
match = dev_get_platdata(&pdev->dev);
|
match = dev_get_platdata(&pdev->dev);
|
||||||
if (!match)
|
if (!match)
|
||||||
@ -370,33 +372,21 @@ static int ti_cpufreq_probe(struct platform_device *pdev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto fail_put_node;
|
goto fail_put_node;
|
||||||
|
|
||||||
ti_opp_table = dev_pm_opp_set_supported_hw(opp_data->cpu_dev,
|
if (opp_data->soc_data->multi_regulator) {
|
||||||
version, VERSION_COUNT);
|
if (opp_data->soc_data->reg_names)
|
||||||
if (IS_ERR(ti_opp_table)) {
|
config.regulator_names = opp_data->soc_data->reg_names;
|
||||||
dev_err(opp_data->cpu_dev,
|
else
|
||||||
"Failed to set supported hardware\n");
|
config.regulator_names = default_reg_names;
|
||||||
ret = PTR_ERR(ti_opp_table);
|
}
|
||||||
|
|
||||||
|
ret = dev_pm_opp_set_config(opp_data->cpu_dev, &config);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(opp_data->cpu_dev, "Failed to set OPP config\n");
|
||||||
goto fail_put_node;
|
goto fail_put_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
opp_data->opp_table = ti_opp_table;
|
|
||||||
|
|
||||||
if (opp_data->soc_data->multi_regulator) {
|
|
||||||
const char * const *reg_names = default_reg_names;
|
|
||||||
|
|
||||||
if (opp_data->soc_data->reg_names)
|
|
||||||
reg_names = opp_data->soc_data->reg_names;
|
|
||||||
ti_opp_table = dev_pm_opp_set_regulators(opp_data->cpu_dev,
|
|
||||||
reg_names,
|
|
||||||
ARRAY_SIZE(default_reg_names));
|
|
||||||
if (IS_ERR(ti_opp_table)) {
|
|
||||||
dev_pm_opp_put_supported_hw(opp_data->opp_table);
|
|
||||||
ret = PTR_ERR(ti_opp_table);
|
|
||||||
goto fail_put_node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
of_node_put(opp_data->opp_node);
|
of_node_put(opp_data->opp_node);
|
||||||
|
|
||||||
register_cpufreq_dt:
|
register_cpufreq_dt:
|
||||||
platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
|
platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ struct exynos_bus {
|
|||||||
|
|
||||||
unsigned long curr_freq;
|
unsigned long curr_freq;
|
||||||
|
|
||||||
struct opp_table *opp_table;
|
int opp_token;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
unsigned int ratio;
|
unsigned int ratio;
|
||||||
};
|
};
|
||||||
@ -161,8 +161,7 @@ static void exynos_bus_exit(struct device *dev)
|
|||||||
|
|
||||||
dev_pm_opp_of_remove_table(dev);
|
dev_pm_opp_of_remove_table(dev);
|
||||||
clk_disable_unprepare(bus->clk);
|
clk_disable_unprepare(bus->clk);
|
||||||
dev_pm_opp_put_regulators(bus->opp_table);
|
dev_pm_opp_put_regulators(bus->opp_token);
|
||||||
bus->opp_table = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exynos_bus_passive_exit(struct device *dev)
|
static void exynos_bus_passive_exit(struct device *dev)
|
||||||
@ -179,18 +178,16 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
|
|||||||
struct exynos_bus *bus)
|
struct exynos_bus *bus)
|
||||||
{
|
{
|
||||||
struct device *dev = bus->dev;
|
struct device *dev = bus->dev;
|
||||||
struct opp_table *opp_table;
|
const char *supplies[] = { "vdd", NULL };
|
||||||
const char *vdd = "vdd";
|
|
||||||
int i, ret, count, size;
|
int i, ret, count, size;
|
||||||
|
|
||||||
opp_table = dev_pm_opp_set_regulators(dev, &vdd, 1);
|
ret = dev_pm_opp_set_regulators(dev, supplies);
|
||||||
if (IS_ERR(opp_table)) {
|
if (ret < 0) {
|
||||||
ret = PTR_ERR(opp_table);
|
|
||||||
dev_err(dev, "failed to set regulators %d\n", ret);
|
dev_err(dev, "failed to set regulators %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus->opp_table = opp_table;
|
bus->opp_token = ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the devfreq-event devices to get the current utilization of
|
* Get the devfreq-event devices to get the current utilization of
|
||||||
@ -236,8 +233,7 @@ static int exynos_bus_parent_parse_of(struct device_node *np,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_regulator:
|
err_regulator:
|
||||||
dev_pm_opp_put_regulators(bus->opp_table);
|
dev_pm_opp_put_regulators(bus->opp_token);
|
||||||
bus->opp_table = NULL;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -459,8 +455,7 @@ err:
|
|||||||
dev_pm_opp_of_remove_table(dev);
|
dev_pm_opp_of_remove_table(dev);
|
||||||
clk_disable_unprepare(bus->clk);
|
clk_disable_unprepare(bus->clk);
|
||||||
err_reg:
|
err_reg:
|
||||||
dev_pm_opp_put_regulators(bus->opp_table);
|
dev_pm_opp_put_regulators(bus->opp_token);
|
||||||
bus->opp_table = NULL;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -821,6 +821,15 @@ static int devm_tegra_devfreq_init_hw(struct device *dev,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tegra_devfreq_config_clks_nop(struct device *dev,
|
||||||
|
struct opp_table *opp_table,
|
||||||
|
struct dev_pm_opp *opp, void *data,
|
||||||
|
bool scaling_down)
|
||||||
|
{
|
||||||
|
/* We want to skip clk configuration via dev_pm_opp_set_opp() */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int tegra_devfreq_probe(struct platform_device *pdev)
|
static int tegra_devfreq_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
||||||
@ -830,6 +839,13 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
long rate;
|
long rate;
|
||||||
int err;
|
int err;
|
||||||
|
const char *clk_names[] = { "actmon", NULL };
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.supported_hw = &hw_version,
|
||||||
|
.supported_hw_count = 1,
|
||||||
|
.clk_names = clk_names,
|
||||||
|
.config_clks = tegra_devfreq_config_clks_nop,
|
||||||
|
};
|
||||||
|
|
||||||
tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
|
tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
|
||||||
if (!tegra)
|
if (!tegra)
|
||||||
@ -874,13 +890,13 @@ static int tegra_devfreq_probe(struct platform_device *pdev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = devm_pm_opp_set_supported_hw(&pdev->dev, &hw_version, 1);
|
err = devm_pm_opp_set_config(&pdev->dev, &config);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "Failed to set supported HW: %d\n", err);
|
dev_err(&pdev->dev, "Failed to set OPP config: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = devm_pm_opp_of_add_table_noclk(&pdev->dev, 0);
|
err = devm_pm_opp_of_add_table_indexed(&pdev->dev, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "Failed to add OPP table: %d\n", err);
|
dev_err(&pdev->dev, "Failed to add OPP table: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
|
@ -111,6 +111,12 @@ int lima_devfreq_init(struct lima_device *ldev)
|
|||||||
struct dev_pm_opp *opp;
|
struct dev_pm_opp *opp;
|
||||||
unsigned long cur_freq;
|
unsigned long cur_freq;
|
||||||
int ret;
|
int ret;
|
||||||
|
const char *regulator_names[] = { "mali", NULL };
|
||||||
|
const char *clk_names[] = { "core", NULL };
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.regulator_names = regulator_names,
|
||||||
|
.clk_names = clk_names,
|
||||||
|
};
|
||||||
|
|
||||||
if (!device_property_present(dev, "operating-points-v2"))
|
if (!device_property_present(dev, "operating-points-v2"))
|
||||||
/* Optional, continue without devfreq */
|
/* Optional, continue without devfreq */
|
||||||
@ -118,11 +124,7 @@ int lima_devfreq_init(struct lima_device *ldev)
|
|||||||
|
|
||||||
spin_lock_init(&ldevfreq->lock);
|
spin_lock_init(&ldevfreq->lock);
|
||||||
|
|
||||||
ret = devm_pm_opp_set_clkname(dev, "core");
|
ret = devm_pm_opp_set_config(dev, &config);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = devm_pm_opp_set_regulators(dev, (const char *[]){ "mali" }, 1);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* Continue if the optional regulator is missing */
|
/* Continue if the optional regulator is missing */
|
||||||
if (ret != -ENODEV)
|
if (ret != -ENODEV)
|
||||||
|
@ -101,8 +101,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names,
|
ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names);
|
||||||
pfdev->comp->num_supplies);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* Continue if the optional regulator is missing */
|
/* Continue if the optional regulator is missing */
|
||||||
if (ret != -ENODEV) {
|
if (ret != -ENODEV) {
|
||||||
|
@ -626,24 +626,29 @@ static int panfrost_remove(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const default_supplies[] = { "mali" };
|
/*
|
||||||
|
* The OPP core wants the supply names to be NULL terminated, but we need the
|
||||||
|
* correct num_supplies value for regulator core. Hence, we NULL terminate here
|
||||||
|
* and then initialize num_supplies with ARRAY_SIZE - 1.
|
||||||
|
*/
|
||||||
|
static const char * const default_supplies[] = { "mali", NULL };
|
||||||
static const struct panfrost_compatible default_data = {
|
static const struct panfrost_compatible default_data = {
|
||||||
.num_supplies = ARRAY_SIZE(default_supplies),
|
.num_supplies = ARRAY_SIZE(default_supplies) - 1,
|
||||||
.supply_names = default_supplies,
|
.supply_names = default_supplies,
|
||||||
.num_pm_domains = 1, /* optional */
|
.num_pm_domains = 1, /* optional */
|
||||||
.pm_domain_names = NULL,
|
.pm_domain_names = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct panfrost_compatible amlogic_data = {
|
static const struct panfrost_compatible amlogic_data = {
|
||||||
.num_supplies = ARRAY_SIZE(default_supplies),
|
.num_supplies = ARRAY_SIZE(default_supplies) - 1,
|
||||||
.supply_names = default_supplies,
|
.supply_names = default_supplies,
|
||||||
.vendor_quirk = panfrost_gpu_amlogic_quirk,
|
.vendor_quirk = panfrost_gpu_amlogic_quirk,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const mediatek_mt8183_supplies[] = { "mali", "sram" };
|
static const char * const mediatek_mt8183_supplies[] = { "mali", "sram", NULL };
|
||||||
static const char * const mediatek_mt8183_pm_domains[] = { "core0", "core1", "core2" };
|
static const char * const mediatek_mt8183_pm_domains[] = { "core0", "core1", "core2" };
|
||||||
static const struct panfrost_compatible mediatek_mt8183_data = {
|
static const struct panfrost_compatible mediatek_mt8183_data = {
|
||||||
.num_supplies = ARRAY_SIZE(mediatek_mt8183_supplies),
|
.num_supplies = ARRAY_SIZE(mediatek_mt8183_supplies) - 1,
|
||||||
.supply_names = mediatek_mt8183_supplies,
|
.supply_names = mediatek_mt8183_supplies,
|
||||||
.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
|
.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
|
||||||
.pm_domain_names = mediatek_mt8183_pm_domains,
|
.pm_domain_names = mediatek_mt8183_pm_domains,
|
||||||
|
@ -875,7 +875,7 @@ static int vcodec_domains_get(struct venus_core *core)
|
|||||||
}
|
}
|
||||||
|
|
||||||
skip_pmdomains:
|
skip_pmdomains:
|
||||||
if (!core->has_opp_table)
|
if (!core->res->opp_pmdomain)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Attach the power domain for setting performance state */
|
/* Attach the power domain for setting performance state */
|
||||||
@ -1007,6 +1007,10 @@ static int core_get_v4(struct venus_core *core)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = vcodec_domains_get(core);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (core->res->opp_pmdomain) {
|
if (core->res->opp_pmdomain) {
|
||||||
ret = devm_pm_opp_of_add_table(dev);
|
ret = devm_pm_opp_of_add_table(dev);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
@ -1017,10 +1021,6 @@ static int core_get_v4(struct venus_core *core)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = vcodec_domains_get(core);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1395,15 +1395,14 @@ err_msg:
|
|||||||
static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
||||||
{
|
{
|
||||||
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
u32 hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
||||||
struct opp_table *hw_opp_table;
|
int opp_token, err;
|
||||||
int err;
|
|
||||||
|
|
||||||
hw_opp_table = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
|
err = dev_pm_opp_set_supported_hw(emc->dev, &hw_version, 1);
|
||||||
err = PTR_ERR_OR_ZERO(hw_opp_table);
|
if (err < 0) {
|
||||||
if (err) {
|
|
||||||
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
|
dev_err(emc->dev, "failed to set OPP supported HW: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
opp_token = err;
|
||||||
|
|
||||||
err = dev_pm_opp_of_add_table(emc->dev);
|
err = dev_pm_opp_of_add_table(emc->dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -1430,7 +1429,7 @@ static int tegra_emc_opp_table_init(struct tegra_emc *emc)
|
|||||||
remove_table:
|
remove_table:
|
||||||
dev_pm_opp_of_remove_table(emc->dev);
|
dev_pm_opp_of_remove_table(emc->dev);
|
||||||
put_hw_table:
|
put_hw_table:
|
||||||
dev_pm_opp_put_supported_hw(hw_opp_table);
|
dev_pm_opp_put_supported_hw(opp_token);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
1581
drivers/opp/core.c
1581
drivers/opp/core.c
File diff suppressed because it is too large
Load Diff
@ -41,7 +41,7 @@
|
|||||||
* the table if any of the mentioned functions have been invoked in the interim.
|
* the table if any of the mentioned functions have been invoked in the interim.
|
||||||
*/
|
*/
|
||||||
int dev_pm_opp_init_cpufreq_table(struct device *dev,
|
int dev_pm_opp_init_cpufreq_table(struct device *dev,
|
||||||
struct cpufreq_frequency_table **table)
|
struct cpufreq_frequency_table **opp_table)
|
||||||
{
|
{
|
||||||
struct dev_pm_opp *opp;
|
struct dev_pm_opp *opp;
|
||||||
struct cpufreq_frequency_table *freq_table = NULL;
|
struct cpufreq_frequency_table *freq_table = NULL;
|
||||||
@ -76,7 +76,7 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
|
|||||||
freq_table[i].driver_data = i;
|
freq_table[i].driver_data = i;
|
||||||
freq_table[i].frequency = CPUFREQ_TABLE_END;
|
freq_table[i].frequency = CPUFREQ_TABLE_END;
|
||||||
|
|
||||||
*table = &freq_table[0];
|
*opp_table = &freq_table[0];
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -94,13 +94,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table);
|
|||||||
* Free up the table allocated by dev_pm_opp_init_cpufreq_table
|
* Free up the table allocated by dev_pm_opp_init_cpufreq_table
|
||||||
*/
|
*/
|
||||||
void dev_pm_opp_free_cpufreq_table(struct device *dev,
|
void dev_pm_opp_free_cpufreq_table(struct device *dev,
|
||||||
struct cpufreq_frequency_table **table)
|
struct cpufreq_frequency_table **opp_table)
|
||||||
{
|
{
|
||||||
if (!table)
|
if (!opp_table)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
kfree(*table);
|
kfree(*opp_table);
|
||||||
*table = NULL;
|
*opp_table = NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
|
EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
|
||||||
#endif /* CONFIG_CPU_FREQ */
|
#endif /* CONFIG_CPU_FREQ */
|
||||||
|
@ -74,6 +74,24 @@ static void opp_debug_create_bw(struct dev_pm_opp *opp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void opp_debug_create_clks(struct dev_pm_opp *opp,
|
||||||
|
struct opp_table *opp_table,
|
||||||
|
struct dentry *pdentry)
|
||||||
|
{
|
||||||
|
char name[12];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (opp_table->clk_count == 1) {
|
||||||
|
debugfs_create_ulong("rate_hz", S_IRUGO, pdentry, &opp->rates[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < opp_table->clk_count; i++) {
|
||||||
|
snprintf(name, sizeof(name), "rate_hz_%d", i);
|
||||||
|
debugfs_create_ulong(name, S_IRUGO, pdentry, &opp->rates[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void opp_debug_create_supplies(struct dev_pm_opp *opp,
|
static void opp_debug_create_supplies(struct dev_pm_opp *opp,
|
||||||
struct opp_table *opp_table,
|
struct opp_table *opp_table,
|
||||||
struct dentry *pdentry)
|
struct dentry *pdentry)
|
||||||
@ -117,10 +135,11 @@ void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
|
|||||||
* Get directory name for OPP.
|
* Get directory name for OPP.
|
||||||
*
|
*
|
||||||
* - Normally rate is unique to each OPP, use it to get unique opp-name.
|
* - Normally rate is unique to each OPP, use it to get unique opp-name.
|
||||||
* - For some devices rate isn't available, use index instead.
|
* - For some devices rate isn't available or there are multiple, use
|
||||||
|
* index instead for them.
|
||||||
*/
|
*/
|
||||||
if (likely(opp->rate))
|
if (likely(opp_table->clk_count == 1 && opp->rates[0]))
|
||||||
id = opp->rate;
|
id = opp->rates[0];
|
||||||
else
|
else
|
||||||
id = _get_opp_count(opp_table);
|
id = _get_opp_count(opp_table);
|
||||||
|
|
||||||
@ -134,7 +153,6 @@ void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
|
|||||||
debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo);
|
debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo);
|
||||||
debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend);
|
debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend);
|
||||||
debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate);
|
debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate);
|
||||||
debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate);
|
|
||||||
debugfs_create_u32("level", S_IRUGO, d, &opp->level);
|
debugfs_create_u32("level", S_IRUGO, d, &opp->level);
|
||||||
debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
|
debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
|
||||||
&opp->clock_latency_ns);
|
&opp->clock_latency_ns);
|
||||||
@ -142,6 +160,7 @@ void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
|
|||||||
opp->of_name = of_node_full_name(opp->np);
|
opp->of_name = of_node_full_name(opp->np);
|
||||||
debugfs_create_str("of_name", S_IRUGO, d, (char **)&opp->of_name);
|
debugfs_create_str("of_name", S_IRUGO, d, (char **)&opp->of_name);
|
||||||
|
|
||||||
|
opp_debug_create_clks(opp, opp_table, d);
|
||||||
opp_debug_create_supplies(opp, opp_table, d);
|
opp_debug_create_supplies(opp, opp_table, d);
|
||||||
opp_debug_create_bw(opp, opp_table, d);
|
opp_debug_create_bw(opp, opp_table, d);
|
||||||
|
|
||||||
|
150
drivers/opp/of.c
150
drivers/opp/of.c
@ -242,20 +242,20 @@ void _of_init_opp_table(struct opp_table *opp_table, struct device *dev,
|
|||||||
opp_table->np = opp_np;
|
opp_table->np = opp_np;
|
||||||
|
|
||||||
_opp_table_alloc_required_tables(opp_table, dev, opp_np);
|
_opp_table_alloc_required_tables(opp_table, dev, opp_np);
|
||||||
of_node_put(opp_np);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _of_clear_opp_table(struct opp_table *opp_table)
|
void _of_clear_opp_table(struct opp_table *opp_table)
|
||||||
{
|
{
|
||||||
_opp_table_free_required_tables(opp_table);
|
_opp_table_free_required_tables(opp_table);
|
||||||
|
of_node_put(opp_table->np);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release all resources previously acquired with a call to
|
* Release all resources previously acquired with a call to
|
||||||
* _of_opp_alloc_required_opps().
|
* _of_opp_alloc_required_opps().
|
||||||
*/
|
*/
|
||||||
void _of_opp_free_required_opps(struct opp_table *opp_table,
|
static void _of_opp_free_required_opps(struct opp_table *opp_table,
|
||||||
struct dev_pm_opp *opp)
|
struct dev_pm_opp *opp)
|
||||||
{
|
{
|
||||||
struct dev_pm_opp **required_opps = opp->required_opps;
|
struct dev_pm_opp **required_opps = opp->required_opps;
|
||||||
int i;
|
int i;
|
||||||
@ -275,6 +275,12 @@ void _of_opp_free_required_opps(struct opp_table *opp_table,
|
|||||||
kfree(required_opps);
|
kfree(required_opps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp)
|
||||||
|
{
|
||||||
|
_of_opp_free_required_opps(opp_table, opp);
|
||||||
|
of_node_put(opp->np);
|
||||||
|
}
|
||||||
|
|
||||||
/* Populate all required OPPs which are part of "required-opps" list */
|
/* Populate all required OPPs which are part of "required-opps" list */
|
||||||
static int _of_opp_alloc_required_opps(struct opp_table *opp_table,
|
static int _of_opp_alloc_required_opps(struct opp_table *opp_table,
|
||||||
struct dev_pm_opp *opp)
|
struct dev_pm_opp *opp)
|
||||||
@ -767,7 +773,51 @@ void dev_pm_opp_of_remove_table(struct device *dev)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
|
EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
|
||||||
|
|
||||||
static int _read_bw(struct dev_pm_opp *new_opp, struct opp_table *table,
|
static int _read_rate(struct dev_pm_opp *new_opp, struct opp_table *opp_table,
|
||||||
|
struct device_node *np)
|
||||||
|
{
|
||||||
|
struct property *prop;
|
||||||
|
int i, count, ret;
|
||||||
|
u64 *rates;
|
||||||
|
|
||||||
|
prop = of_find_property(np, "opp-hz", NULL);
|
||||||
|
if (!prop)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
count = prop->length / sizeof(u64);
|
||||||
|
if (opp_table->clk_count != count) {
|
||||||
|
pr_err("%s: Count mismatch between opp-hz and clk_count (%d %d)\n",
|
||||||
|
__func__, count, opp_table->clk_count);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rates = kmalloc_array(count, sizeof(*rates), GFP_KERNEL);
|
||||||
|
if (!rates)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = of_property_read_u64_array(np, "opp-hz", rates, count);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Error parsing opp-hz: %d\n", __func__, ret);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Rate is defined as an unsigned long in clk API, and so
|
||||||
|
* casting explicitly to its type. Must be fixed once rate is 64
|
||||||
|
* bit guaranteed in clk API.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
new_opp->rates[i] = (unsigned long)rates[i];
|
||||||
|
|
||||||
|
/* This will happen for frequencies > 4.29 GHz */
|
||||||
|
WARN_ON(new_opp->rates[i] != rates[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(rates);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _read_bw(struct dev_pm_opp *new_opp, struct opp_table *opp_table,
|
||||||
struct device_node *np, bool peak)
|
struct device_node *np, bool peak)
|
||||||
{
|
{
|
||||||
const char *name = peak ? "opp-peak-kBps" : "opp-avg-kBps";
|
const char *name = peak ? "opp-peak-kBps" : "opp-avg-kBps";
|
||||||
@ -780,9 +830,9 @@ static int _read_bw(struct dev_pm_opp *new_opp, struct opp_table *table,
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
count = prop->length / sizeof(u32);
|
count = prop->length / sizeof(u32);
|
||||||
if (table->path_count != count) {
|
if (opp_table->path_count != count) {
|
||||||
pr_err("%s: Mismatch between %s and paths (%d %d)\n",
|
pr_err("%s: Mismatch between %s and paths (%d %d)\n",
|
||||||
__func__, name, count, table->path_count);
|
__func__, name, count, opp_table->path_count);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -808,34 +858,27 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _read_opp_key(struct dev_pm_opp *new_opp, struct opp_table *table,
|
static int _read_opp_key(struct dev_pm_opp *new_opp,
|
||||||
struct device_node *np, bool *rate_not_available)
|
struct opp_table *opp_table, struct device_node *np)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
u64 rate;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = of_property_read_u64(np, "opp-hz", &rate);
|
ret = _read_rate(new_opp, opp_table, np);
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
/*
|
|
||||||
* Rate is defined as an unsigned long in clk API, and so
|
|
||||||
* casting explicitly to its type. Must be fixed once rate is 64
|
|
||||||
* bit guaranteed in clk API.
|
|
||||||
*/
|
|
||||||
new_opp->rate = (unsigned long)rate;
|
|
||||||
found = true;
|
found = true;
|
||||||
}
|
else if (ret != -ENODEV)
|
||||||
*rate_not_available = !!ret;
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bandwidth consists of peak and average (optional) values:
|
* Bandwidth consists of peak and average (optional) values:
|
||||||
* opp-peak-kBps = <path1_value path2_value>;
|
* opp-peak-kBps = <path1_value path2_value>;
|
||||||
* opp-avg-kBps = <path1_value path2_value>;
|
* opp-avg-kBps = <path1_value path2_value>;
|
||||||
*/
|
*/
|
||||||
ret = _read_bw(new_opp, table, np, true);
|
ret = _read_bw(new_opp, opp_table, np, true);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
found = true;
|
found = true;
|
||||||
ret = _read_bw(new_opp, table, np, false);
|
ret = _read_bw(new_opp, opp_table, np, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The properties were found but we failed to parse them */
|
/* The properties were found but we failed to parse them */
|
||||||
@ -881,13 +924,12 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
|
|||||||
struct dev_pm_opp *new_opp;
|
struct dev_pm_opp *new_opp;
|
||||||
u32 val;
|
u32 val;
|
||||||
int ret;
|
int ret;
|
||||||
bool rate_not_available = false;
|
|
||||||
|
|
||||||
new_opp = _opp_allocate(opp_table);
|
new_opp = _opp_allocate(opp_table);
|
||||||
if (!new_opp)
|
if (!new_opp)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
ret = _read_opp_key(new_opp, opp_table, np, &rate_not_available);
|
ret = _read_opp_key(new_opp, opp_table, np);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "%s: opp key field not found\n", __func__);
|
dev_err(dev, "%s: opp key field not found\n", __func__);
|
||||||
goto free_opp;
|
goto free_opp;
|
||||||
@ -895,14 +937,14 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
|
|||||||
|
|
||||||
/* Check if the OPP supports hardware's hierarchy of versions or not */
|
/* Check if the OPP supports hardware's hierarchy of versions or not */
|
||||||
if (!_opp_is_supported(dev, opp_table, np)) {
|
if (!_opp_is_supported(dev, opp_table, np)) {
|
||||||
dev_dbg(dev, "OPP not supported by hardware: %lu\n",
|
dev_dbg(dev, "OPP not supported by hardware: %s\n",
|
||||||
new_opp->rate);
|
of_node_full_name(np));
|
||||||
goto free_opp;
|
goto free_opp;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_opp->turbo = of_property_read_bool(np, "turbo-mode");
|
new_opp->turbo = of_property_read_bool(np, "turbo-mode");
|
||||||
|
|
||||||
new_opp->np = np;
|
new_opp->np = of_node_get(np);
|
||||||
new_opp->dynamic = false;
|
new_opp->dynamic = false;
|
||||||
new_opp->available = true;
|
new_opp->available = true;
|
||||||
|
|
||||||
@ -920,7 +962,7 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
|
|||||||
if (opp_table->is_genpd)
|
if (opp_table->is_genpd)
|
||||||
new_opp->pstate = pm_genpd_opp_to_performance_state(dev, new_opp);
|
new_opp->pstate = pm_genpd_opp_to_performance_state(dev, new_opp);
|
||||||
|
|
||||||
ret = _opp_add(dev, new_opp, opp_table, rate_not_available);
|
ret = _opp_add(dev, new_opp, opp_table);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* Don't return error for duplicate OPPs */
|
/* Don't return error for duplicate OPPs */
|
||||||
if (ret == -EBUSY)
|
if (ret == -EBUSY)
|
||||||
@ -931,8 +973,8 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
|
|||||||
/* OPP to select on device suspend */
|
/* OPP to select on device suspend */
|
||||||
if (of_property_read_bool(np, "opp-suspend")) {
|
if (of_property_read_bool(np, "opp-suspend")) {
|
||||||
if (opp_table->suspend_opp) {
|
if (opp_table->suspend_opp) {
|
||||||
/* Pick the OPP with higher rate as suspend OPP */
|
/* Pick the OPP with higher rate/bw/level as suspend OPP */
|
||||||
if (new_opp->rate > opp_table->suspend_opp->rate) {
|
if (_opp_compare_key(opp_table, new_opp, opp_table->suspend_opp) == 1) {
|
||||||
opp_table->suspend_opp->suspend = false;
|
opp_table->suspend_opp->suspend = false;
|
||||||
new_opp->suspend = true;
|
new_opp->suspend = true;
|
||||||
opp_table->suspend_opp = new_opp;
|
opp_table->suspend_opp = new_opp;
|
||||||
@ -947,7 +989,7 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
|
|||||||
opp_table->clock_latency_ns_max = new_opp->clock_latency_ns;
|
opp_table->clock_latency_ns_max = new_opp->clock_latency_ns;
|
||||||
|
|
||||||
pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu level:%u\n",
|
pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu level:%u\n",
|
||||||
__func__, new_opp->turbo, new_opp->rate,
|
__func__, new_opp->turbo, new_opp->rates[0],
|
||||||
new_opp->supplies[0].u_volt, new_opp->supplies[0].u_volt_min,
|
new_opp->supplies[0].u_volt, new_opp->supplies[0].u_volt_min,
|
||||||
new_opp->supplies[0].u_volt_max, new_opp->clock_latency_ns,
|
new_opp->supplies[0].u_volt_max, new_opp->clock_latency_ns,
|
||||||
new_opp->level);
|
new_opp->level);
|
||||||
@ -1084,7 +1126,7 @@ remove_static_opp:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _of_add_table_indexed(struct device *dev, int index, bool getclk)
|
static int _of_add_table_indexed(struct device *dev, int index)
|
||||||
{
|
{
|
||||||
struct opp_table *opp_table;
|
struct opp_table *opp_table;
|
||||||
int ret, count;
|
int ret, count;
|
||||||
@ -1100,7 +1142,7 @@ static int _of_add_table_indexed(struct device *dev, int index, bool getclk)
|
|||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
opp_table = _add_opp_table_indexed(dev, index, getclk);
|
opp_table = _add_opp_table_indexed(dev, index, true);
|
||||||
if (IS_ERR(opp_table))
|
if (IS_ERR(opp_table))
|
||||||
return PTR_ERR(opp_table);
|
return PTR_ERR(opp_table);
|
||||||
|
|
||||||
@ -1124,11 +1166,11 @@ static void devm_pm_opp_of_table_release(void *data)
|
|||||||
dev_pm_opp_of_remove_table(data);
|
dev_pm_opp_of_remove_table(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _devm_of_add_table_indexed(struct device *dev, int index, bool getclk)
|
static int _devm_of_add_table_indexed(struct device *dev, int index)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = _of_add_table_indexed(dev, index, getclk);
|
ret = _of_add_table_indexed(dev, index);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1156,7 +1198,7 @@ static int _devm_of_add_table_indexed(struct device *dev, int index, bool getclk
|
|||||||
*/
|
*/
|
||||||
int devm_pm_opp_of_add_table(struct device *dev)
|
int devm_pm_opp_of_add_table(struct device *dev)
|
||||||
{
|
{
|
||||||
return _devm_of_add_table_indexed(dev, 0, true);
|
return _devm_of_add_table_indexed(dev, 0);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_pm_opp_of_add_table);
|
EXPORT_SYMBOL_GPL(devm_pm_opp_of_add_table);
|
||||||
|
|
||||||
@ -1179,7 +1221,7 @@ EXPORT_SYMBOL_GPL(devm_pm_opp_of_add_table);
|
|||||||
*/
|
*/
|
||||||
int dev_pm_opp_of_add_table(struct device *dev)
|
int dev_pm_opp_of_add_table(struct device *dev)
|
||||||
{
|
{
|
||||||
return _of_add_table_indexed(dev, 0, true);
|
return _of_add_table_indexed(dev, 0);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
|
EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
|
||||||
|
|
||||||
@ -1195,7 +1237,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
|
|||||||
*/
|
*/
|
||||||
int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
|
int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
|
||||||
{
|
{
|
||||||
return _of_add_table_indexed(dev, index, true);
|
return _of_add_table_indexed(dev, index);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table_indexed);
|
EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table_indexed);
|
||||||
|
|
||||||
@ -1208,42 +1250,10 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table_indexed);
|
|||||||
*/
|
*/
|
||||||
int devm_pm_opp_of_add_table_indexed(struct device *dev, int index)
|
int devm_pm_opp_of_add_table_indexed(struct device *dev, int index)
|
||||||
{
|
{
|
||||||
return _devm_of_add_table_indexed(dev, index, true);
|
return _devm_of_add_table_indexed(dev, index);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_pm_opp_of_add_table_indexed);
|
EXPORT_SYMBOL_GPL(devm_pm_opp_of_add_table_indexed);
|
||||||
|
|
||||||
/**
|
|
||||||
* dev_pm_opp_of_add_table_noclk() - Initialize indexed opp table from device
|
|
||||||
* tree without getting clk for device.
|
|
||||||
* @dev: device pointer used to lookup OPP table.
|
|
||||||
* @index: Index number.
|
|
||||||
*
|
|
||||||
* Register the initial OPP table with the OPP library for given device only
|
|
||||||
* using the "operating-points-v2" property. Do not try to get the clk for the
|
|
||||||
* device.
|
|
||||||
*
|
|
||||||
* Return: Refer to dev_pm_opp_of_add_table() for return values.
|
|
||||||
*/
|
|
||||||
int dev_pm_opp_of_add_table_noclk(struct device *dev, int index)
|
|
||||||
{
|
|
||||||
return _of_add_table_indexed(dev, index, false);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table_noclk);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* devm_pm_opp_of_add_table_noclk() - Initialize indexed opp table from device
|
|
||||||
* tree without getting clk for device.
|
|
||||||
* @dev: device pointer used to lookup OPP table.
|
|
||||||
* @index: Index number.
|
|
||||||
*
|
|
||||||
* This is a resource-managed variant of dev_pm_opp_of_add_table_noclk().
|
|
||||||
*/
|
|
||||||
int devm_pm_opp_of_add_table_noclk(struct device *dev, int index)
|
|
||||||
{
|
|
||||||
return _devm_of_add_table_indexed(dev, index, false);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(devm_pm_opp_of_add_table_noclk);
|
|
||||||
|
|
||||||
/* CPU device specific helpers */
|
/* CPU device specific helpers */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +28,27 @@ extern struct mutex opp_table_lock;
|
|||||||
|
|
||||||
extern struct list_head opp_tables, lazy_opp_tables;
|
extern struct list_head opp_tables, lazy_opp_tables;
|
||||||
|
|
||||||
|
/* OPP Config flags */
|
||||||
|
#define OPP_CONFIG_CLK BIT(0)
|
||||||
|
#define OPP_CONFIG_REGULATOR BIT(1)
|
||||||
|
#define OPP_CONFIG_REGULATOR_HELPER BIT(2)
|
||||||
|
#define OPP_CONFIG_PROP_NAME BIT(3)
|
||||||
|
#define OPP_CONFIG_SUPPORTED_HW BIT(4)
|
||||||
|
#define OPP_CONFIG_GENPD BIT(5)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct opp_config_data - data for set config operations
|
||||||
|
* @opp_table: OPP table
|
||||||
|
* @flags: OPP config flags
|
||||||
|
*
|
||||||
|
* This structure stores the OPP config information for each OPP table
|
||||||
|
* configuration by the callers.
|
||||||
|
*/
|
||||||
|
struct opp_config_data {
|
||||||
|
struct opp_table *opp_table;
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal data structure organization with the OPP layer library is as
|
* Internal data structure organization with the OPP layer library is as
|
||||||
* follows:
|
* follows:
|
||||||
@ -58,7 +79,7 @@ extern struct list_head opp_tables, lazy_opp_tables;
|
|||||||
* @suspend: true if suspend OPP
|
* @suspend: true if suspend OPP
|
||||||
* @removed: flag indicating that OPP's reference is dropped by OPP core.
|
* @removed: flag indicating that OPP's reference is dropped by OPP core.
|
||||||
* @pstate: Device's power domain's performance state.
|
* @pstate: Device's power domain's performance state.
|
||||||
* @rate: Frequency in hertz
|
* @rates: Frequencies in hertz
|
||||||
* @level: Performance level
|
* @level: Performance level
|
||||||
* @supplies: Power supplies voltage/current values
|
* @supplies: Power supplies voltage/current values
|
||||||
* @bandwidth: Interconnect bandwidth values
|
* @bandwidth: Interconnect bandwidth values
|
||||||
@ -81,7 +102,7 @@ struct dev_pm_opp {
|
|||||||
bool suspend;
|
bool suspend;
|
||||||
bool removed;
|
bool removed;
|
||||||
unsigned int pstate;
|
unsigned int pstate;
|
||||||
unsigned long rate;
|
unsigned long *rates;
|
||||||
unsigned int level;
|
unsigned int level;
|
||||||
|
|
||||||
struct dev_pm_opp_supply *supplies;
|
struct dev_pm_opp_supply *supplies;
|
||||||
@ -138,7 +159,7 @@ enum opp_table_access {
|
|||||||
* @clock_latency_ns_max: Max clock latency in nanoseconds.
|
* @clock_latency_ns_max: Max clock latency in nanoseconds.
|
||||||
* @parsed_static_opps: Count of devices for which OPPs are initialized from DT.
|
* @parsed_static_opps: Count of devices for which OPPs are initialized from DT.
|
||||||
* @shared_opp: OPP is shared between multiple devices.
|
* @shared_opp: OPP is shared between multiple devices.
|
||||||
* @current_rate: Currently configured frequency.
|
* @rate_clk_single: Currently configured frequency for single clk.
|
||||||
* @current_opp: Currently configured OPP for the table.
|
* @current_opp: Currently configured OPP for the table.
|
||||||
* @suspend_opp: Pointer to OPP to be used during device suspend.
|
* @suspend_opp: Pointer to OPP to be used during device suspend.
|
||||||
* @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers.
|
* @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers.
|
||||||
@ -149,7 +170,11 @@ enum opp_table_access {
|
|||||||
* @supported_hw: Array of version number to support.
|
* @supported_hw: Array of version number to support.
|
||||||
* @supported_hw_count: Number of elements in supported_hw array.
|
* @supported_hw_count: Number of elements in supported_hw array.
|
||||||
* @prop_name: A name to postfix to many DT properties, while parsing them.
|
* @prop_name: A name to postfix to many DT properties, while parsing them.
|
||||||
* @clk: Device's clock handle
|
* @config_clks: Platform specific config_clks() callback.
|
||||||
|
* @clks: Device's clock handles, for multiple clocks.
|
||||||
|
* @clk: Device's clock handle, for single clock.
|
||||||
|
* @clk_count: Number of clocks.
|
||||||
|
* @config_regulators: Platform specific config_regulators() callback.
|
||||||
* @regulators: Supply regulators
|
* @regulators: Supply regulators
|
||||||
* @regulator_count: Number of power supply regulators. Its value can be -1
|
* @regulator_count: Number of power supply regulators. Its value can be -1
|
||||||
* (uninitialized), 0 (no opp-microvolt property) or > 0 (has opp-microvolt
|
* (uninitialized), 0 (no opp-microvolt property) or > 0 (has opp-microvolt
|
||||||
@ -159,9 +184,6 @@ enum opp_table_access {
|
|||||||
* @enabled: Set to true if the device's resources are enabled/configured.
|
* @enabled: Set to true if the device's resources are enabled/configured.
|
||||||
* @genpd_performance_state: Device's power domain support performance state.
|
* @genpd_performance_state: Device's power domain support performance state.
|
||||||
* @is_genpd: Marks if the OPP table belongs to a genpd.
|
* @is_genpd: Marks if the OPP table belongs to a genpd.
|
||||||
* @set_opp: Platform specific set_opp callback
|
|
||||||
* @sod_supplies: Set opp data supplies
|
|
||||||
* @set_opp_data: Data to be passed to set_opp callback
|
|
||||||
* @dentry: debugfs dentry pointer of the real device directory (not links).
|
* @dentry: debugfs dentry pointer of the real device directory (not links).
|
||||||
* @dentry_name: Name of the real dentry.
|
* @dentry_name: Name of the real dentry.
|
||||||
*
|
*
|
||||||
@ -188,7 +210,7 @@ struct opp_table {
|
|||||||
|
|
||||||
unsigned int parsed_static_opps;
|
unsigned int parsed_static_opps;
|
||||||
enum opp_table_access shared_opp;
|
enum opp_table_access shared_opp;
|
||||||
unsigned long current_rate;
|
unsigned long rate_clk_single;
|
||||||
struct dev_pm_opp *current_opp;
|
struct dev_pm_opp *current_opp;
|
||||||
struct dev_pm_opp *suspend_opp;
|
struct dev_pm_opp *suspend_opp;
|
||||||
|
|
||||||
@ -200,7 +222,11 @@ struct opp_table {
|
|||||||
unsigned int *supported_hw;
|
unsigned int *supported_hw;
|
||||||
unsigned int supported_hw_count;
|
unsigned int supported_hw_count;
|
||||||
const char *prop_name;
|
const char *prop_name;
|
||||||
|
config_clks_t config_clks;
|
||||||
|
struct clk **clks;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
int clk_count;
|
||||||
|
config_regulators_t config_regulators;
|
||||||
struct regulator **regulators;
|
struct regulator **regulators;
|
||||||
int regulator_count;
|
int regulator_count;
|
||||||
struct icc_path **paths;
|
struct icc_path **paths;
|
||||||
@ -209,10 +235,6 @@ struct opp_table {
|
|||||||
bool genpd_performance_state;
|
bool genpd_performance_state;
|
||||||
bool is_genpd;
|
bool is_genpd;
|
||||||
|
|
||||||
int (*set_opp)(struct dev_pm_set_opp_data *data);
|
|
||||||
struct dev_pm_opp_supply *sod_supplies;
|
|
||||||
struct dev_pm_set_opp_data *set_opp_data;
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
char dentry_name[NAME_MAX];
|
char dentry_name[NAME_MAX];
|
||||||
@ -228,8 +250,8 @@ struct opp_table *_find_opp_table(struct device *dev);
|
|||||||
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
|
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
|
||||||
struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
|
struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
|
||||||
void _opp_free(struct dev_pm_opp *opp);
|
void _opp_free(struct dev_pm_opp *opp);
|
||||||
int _opp_compare_key(struct dev_pm_opp *opp1, struct dev_pm_opp *opp2);
|
int _opp_compare_key(struct opp_table *opp_table, struct dev_pm_opp *opp1, struct dev_pm_opp *opp2);
|
||||||
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table, bool rate_not_available);
|
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
|
||||||
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
|
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
|
||||||
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
|
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
|
||||||
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
|
struct opp_table *_add_opp_table_indexed(struct device *dev, int index, bool getclk);
|
||||||
@ -245,14 +267,12 @@ static inline bool lazy_linking_pending(struct opp_table *opp_table)
|
|||||||
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index);
|
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index);
|
||||||
void _of_clear_opp_table(struct opp_table *opp_table);
|
void _of_clear_opp_table(struct opp_table *opp_table);
|
||||||
struct opp_table *_managed_opp(struct device *dev, int index);
|
struct opp_table *_managed_opp(struct device *dev, int index);
|
||||||
void _of_opp_free_required_opps(struct opp_table *opp_table,
|
void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp);
|
||||||
struct dev_pm_opp *opp);
|
|
||||||
#else
|
#else
|
||||||
static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {}
|
static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {}
|
||||||
static inline void _of_clear_opp_table(struct opp_table *opp_table) {}
|
static inline void _of_clear_opp_table(struct opp_table *opp_table) {}
|
||||||
static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; }
|
static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; }
|
||||||
static inline void _of_opp_free_required_opps(struct opp_table *opp_table,
|
static inline void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp) {}
|
||||||
struct dev_pm_opp *opp) {}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
@ -36,11 +36,15 @@ struct ti_opp_supply_optimum_voltage_table {
|
|||||||
* @vdd_table: Optimized voltage mapping table
|
* @vdd_table: Optimized voltage mapping table
|
||||||
* @num_vdd_table: number of entries in vdd_table
|
* @num_vdd_table: number of entries in vdd_table
|
||||||
* @vdd_absolute_max_voltage_uv: absolute maximum voltage in UV for the supply
|
* @vdd_absolute_max_voltage_uv: absolute maximum voltage in UV for the supply
|
||||||
|
* @old_supplies: Placeholder for supplies information for old OPP.
|
||||||
|
* @new_supplies: Placeholder for supplies information for new OPP.
|
||||||
*/
|
*/
|
||||||
struct ti_opp_supply_data {
|
struct ti_opp_supply_data {
|
||||||
struct ti_opp_supply_optimum_voltage_table *vdd_table;
|
struct ti_opp_supply_optimum_voltage_table *vdd_table;
|
||||||
u32 num_vdd_table;
|
u32 num_vdd_table;
|
||||||
u32 vdd_absolute_max_voltage_uv;
|
u32 vdd_absolute_max_voltage_uv;
|
||||||
|
struct dev_pm_opp_supply old_supplies[2];
|
||||||
|
struct dev_pm_opp_supply new_supplies[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ti_opp_supply_data opp_data;
|
static struct ti_opp_supply_data opp_data;
|
||||||
@ -266,27 +270,32 @@ static int _opp_set_voltage(struct device *dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/* Do the opp supply transition */
|
||||||
* ti_opp_supply_set_opp() - do the opp supply transition
|
static int ti_opp_config_regulators(struct device *dev,
|
||||||
* @data: information on regulators and new and old opps provided by
|
struct dev_pm_opp *old_opp, struct dev_pm_opp *new_opp,
|
||||||
* opp core to use in transition
|
struct regulator **regulators, unsigned int count)
|
||||||
*
|
|
||||||
* Return: If successful, 0, else appropriate error value.
|
|
||||||
*/
|
|
||||||
static int ti_opp_supply_set_opp(struct dev_pm_set_opp_data *data)
|
|
||||||
{
|
{
|
||||||
struct dev_pm_opp_supply *old_supply_vdd = &data->old_opp.supplies[0];
|
struct dev_pm_opp_supply *old_supply_vdd = &opp_data.old_supplies[0];
|
||||||
struct dev_pm_opp_supply *old_supply_vbb = &data->old_opp.supplies[1];
|
struct dev_pm_opp_supply *old_supply_vbb = &opp_data.old_supplies[1];
|
||||||
struct dev_pm_opp_supply *new_supply_vdd = &data->new_opp.supplies[0];
|
struct dev_pm_opp_supply *new_supply_vdd = &opp_data.new_supplies[0];
|
||||||
struct dev_pm_opp_supply *new_supply_vbb = &data->new_opp.supplies[1];
|
struct dev_pm_opp_supply *new_supply_vbb = &opp_data.new_supplies[1];
|
||||||
struct device *dev = data->dev;
|
struct regulator *vdd_reg = regulators[0];
|
||||||
unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate;
|
struct regulator *vbb_reg = regulators[1];
|
||||||
struct clk *clk = data->clk;
|
unsigned long old_freq, freq;
|
||||||
struct regulator *vdd_reg = data->regulators[0];
|
|
||||||
struct regulator *vbb_reg = data->regulators[1];
|
|
||||||
int vdd_uv;
|
int vdd_uv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* We must have two regulators here */
|
||||||
|
WARN_ON(count != 2);
|
||||||
|
|
||||||
|
/* Fetch supplies and freq information from OPP core */
|
||||||
|
ret = dev_pm_opp_get_supplies(new_opp, opp_data.new_supplies);
|
||||||
|
WARN_ON(ret);
|
||||||
|
|
||||||
|
old_freq = dev_pm_opp_get_freq(old_opp);
|
||||||
|
freq = dev_pm_opp_get_freq(new_opp);
|
||||||
|
WARN_ON(!old_freq || !freq);
|
||||||
|
|
||||||
vdd_uv = _get_optimal_vdd_voltage(dev, &opp_data,
|
vdd_uv = _get_optimal_vdd_voltage(dev, &opp_data,
|
||||||
new_supply_vdd->u_volt);
|
new_supply_vdd->u_volt);
|
||||||
|
|
||||||
@ -303,39 +312,24 @@ static int ti_opp_supply_set_opp(struct dev_pm_set_opp_data *data)
|
|||||||
ret = _opp_set_voltage(dev, new_supply_vbb, 0, vbb_reg, "vbb");
|
ret = _opp_set_voltage(dev, new_supply_vbb, 0, vbb_reg, "vbb");
|
||||||
if (ret)
|
if (ret)
|
||||||
goto restore_voltage;
|
goto restore_voltage;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
/* Change frequency */
|
|
||||||
dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n",
|
|
||||||
__func__, old_freq, freq);
|
|
||||||
|
|
||||||
ret = clk_set_rate(clk, freq);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "%s: failed to set clock rate: %d\n", __func__,
|
|
||||||
ret);
|
|
||||||
goto restore_voltage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scaling down? Scale voltage after frequency */
|
|
||||||
if (freq < old_freq) {
|
|
||||||
ret = _opp_set_voltage(dev, new_supply_vbb, 0, vbb_reg, "vbb");
|
ret = _opp_set_voltage(dev, new_supply_vbb, 0, vbb_reg, "vbb");
|
||||||
if (ret)
|
if (ret)
|
||||||
goto restore_freq;
|
goto restore_voltage;
|
||||||
|
|
||||||
ret = _opp_set_voltage(dev, new_supply_vdd, vdd_uv, vdd_reg,
|
ret = _opp_set_voltage(dev, new_supply_vdd, vdd_uv, vdd_reg,
|
||||||
"vdd");
|
"vdd");
|
||||||
if (ret)
|
if (ret)
|
||||||
goto restore_freq;
|
goto restore_voltage;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
restore_freq:
|
|
||||||
ret = clk_set_rate(clk, old_freq);
|
|
||||||
if (ret)
|
|
||||||
dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
|
|
||||||
__func__, old_freq);
|
|
||||||
restore_voltage:
|
restore_voltage:
|
||||||
|
/* Fetch old supplies information only if required */
|
||||||
|
ret = dev_pm_opp_get_supplies(old_opp, opp_data.old_supplies);
|
||||||
|
WARN_ON(ret);
|
||||||
|
|
||||||
/* This shouldn't harm even if the voltages weren't updated earlier */
|
/* This shouldn't harm even if the voltages weren't updated earlier */
|
||||||
if (old_supply_vdd->u_volt) {
|
if (old_supply_vdd->u_volt) {
|
||||||
ret = _opp_set_voltage(dev, old_supply_vbb, 0, vbb_reg, "vbb");
|
ret = _opp_set_voltage(dev, old_supply_vbb, 0, vbb_reg, "vbb");
|
||||||
@ -405,9 +399,8 @@ static int ti_opp_supply_probe(struct platform_device *pdev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = PTR_ERR_OR_ZERO(dev_pm_opp_register_set_opp_helper(cpu_dev,
|
ret = dev_pm_opp_set_config_regulators(cpu_dev, ti_opp_config_regulators);
|
||||||
ti_opp_supply_set_opp));
|
if (ret < 0)
|
||||||
if (ret)
|
|
||||||
_free_optimized_voltages(dev, &opp_data);
|
_free_optimized_voltages(dev, &opp_data);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -107,29 +107,46 @@ int devm_tegra_core_dev_init_opp_table(struct device *dev,
|
|||||||
{
|
{
|
||||||
u32 hw_version;
|
u32 hw_version;
|
||||||
int err;
|
int err;
|
||||||
|
/*
|
||||||
|
* The clk's connection id to set is NULL and this is a NULL terminated
|
||||||
|
* array, hence two NULL entries.
|
||||||
|
*/
|
||||||
|
const char *clk_names[] = { NULL, NULL };
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
/*
|
||||||
|
* For some devices we don't have any OPP table in the DT, and
|
||||||
|
* in order to use the same code path for all the devices, we
|
||||||
|
* create a dummy OPP table for them via this. The dummy OPP
|
||||||
|
* table is only capable of doing clk_set_rate() on invocation
|
||||||
|
* of dev_pm_opp_set_rate() and doesn't provide any other
|
||||||
|
* functionality.
|
||||||
|
*/
|
||||||
|
.clk_names = clk_names,
|
||||||
|
};
|
||||||
|
|
||||||
err = devm_pm_opp_set_clkname(dev, NULL);
|
if (of_machine_is_compatible("nvidia,tegra20")) {
|
||||||
if (err) {
|
|
||||||
dev_err(dev, "failed to set OPP clk: %d\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tegra114+ doesn't support OPP yet */
|
|
||||||
if (!of_machine_is_compatible("nvidia,tegra20") &&
|
|
||||||
!of_machine_is_compatible("nvidia,tegra30"))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (of_machine_is_compatible("nvidia,tegra20"))
|
|
||||||
hw_version = BIT(tegra_sku_info.soc_process_id);
|
hw_version = BIT(tegra_sku_info.soc_process_id);
|
||||||
else
|
config.supported_hw = &hw_version;
|
||||||
|
config.supported_hw_count = 1;
|
||||||
|
} else if (of_machine_is_compatible("nvidia,tegra30")) {
|
||||||
hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
hw_version = BIT(tegra_sku_info.soc_speedo_id);
|
||||||
|
config.supported_hw = &hw_version;
|
||||||
|
config.supported_hw_count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
err = devm_pm_opp_set_supported_hw(dev, &hw_version, 1);
|
err = devm_pm_opp_set_config(dev, &config);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(dev, "failed to set OPP supported HW: %d\n", err);
|
dev_err(dev, "failed to set OPP config: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tegra114+ doesn't support OPP yet, return early for non tegra20/30
|
||||||
|
* case.
|
||||||
|
*/
|
||||||
|
if (!config.supported_hw)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Older device-trees have an empty OPP table, we will get
|
* Older device-trees have an empty OPP table, we will get
|
||||||
* -ENODEV from devm_pm_opp_of_add_table() in this case.
|
* -ENODEV from devm_pm_opp_of_add_table() in this case.
|
||||||
|
@ -1384,7 +1384,7 @@ tegra_pmc_core_pd_opp_to_performance_state(struct generic_pm_domain *genpd,
|
|||||||
static int tegra_pmc_core_pd_add(struct tegra_pmc *pmc, struct device_node *np)
|
static int tegra_pmc_core_pd_add(struct tegra_pmc *pmc, struct device_node *np)
|
||||||
{
|
{
|
||||||
struct generic_pm_domain *genpd;
|
struct generic_pm_domain *genpd;
|
||||||
const char *rname = "core";
|
const char *rname[] = { "core", NULL};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
genpd = devm_kzalloc(pmc->dev, sizeof(*genpd), GFP_KERNEL);
|
genpd = devm_kzalloc(pmc->dev, sizeof(*genpd), GFP_KERNEL);
|
||||||
@ -1395,7 +1395,7 @@ static int tegra_pmc_core_pd_add(struct tegra_pmc *pmc, struct device_node *np)
|
|||||||
genpd->set_performance_state = tegra_pmc_core_pd_set_performance_state;
|
genpd->set_performance_state = tegra_pmc_core_pd_set_performance_state;
|
||||||
genpd->opp_to_performance_state = tegra_pmc_core_pd_opp_to_performance_state;
|
genpd->opp_to_performance_state = tegra_pmc_core_pd_opp_to_performance_state;
|
||||||
|
|
||||||
err = devm_pm_opp_set_regulators(pmc->dev, &rname, 1);
|
err = devm_pm_opp_set_regulators(pmc->dev, rname);
|
||||||
if (err)
|
if (err)
|
||||||
return dev_err_probe(pmc->dev, err,
|
return dev_err_probe(pmc->dev, err,
|
||||||
"failed to set core OPP regulator\n");
|
"failed to set core OPP regulator\n");
|
||||||
|
@ -57,37 +57,39 @@ struct dev_pm_opp_icc_bw {
|
|||||||
u32 peak;
|
u32 peak;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
typedef int (*config_regulators_t)(struct device *dev,
|
||||||
* struct dev_pm_opp_info - OPP freq/voltage/current values
|
struct dev_pm_opp *old_opp, struct dev_pm_opp *new_opp,
|
||||||
* @rate: Target clk rate in hz
|
struct regulator **regulators, unsigned int count);
|
||||||
* @supplies: Array of voltage/current values for all power supplies
|
|
||||||
*
|
typedef int (*config_clks_t)(struct device *dev, struct opp_table *opp_table,
|
||||||
* This structure stores the freq/voltage/current values for a single OPP.
|
struct dev_pm_opp *opp, void *data, bool scaling_down);
|
||||||
*/
|
|
||||||
struct dev_pm_opp_info {
|
|
||||||
unsigned long rate;
|
|
||||||
struct dev_pm_opp_supply *supplies;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct dev_pm_set_opp_data - Set OPP data
|
* struct dev_pm_opp_config - Device OPP configuration values
|
||||||
* @old_opp: Old OPP info
|
* @clk_names: Clk names, NULL terminated array.
|
||||||
* @new_opp: New OPP info
|
* @config_clks: Custom set clk helper.
|
||||||
* @regulators: Array of regulator pointers
|
* @prop_name: Name to postfix to properties.
|
||||||
* @regulator_count: Number of regulators
|
* @config_regulators: Custom set regulator helper.
|
||||||
* @clk: Pointer to clk
|
* @supported_hw: Array of hierarchy of versions to match.
|
||||||
* @dev: Pointer to the struct device
|
* @supported_hw_count: Number of elements in the array.
|
||||||
|
* @regulator_names: Array of pointers to the names of the regulator, NULL terminated.
|
||||||
|
* @genpd_names: Null terminated array of pointers containing names of genpd to
|
||||||
|
* attach.
|
||||||
|
* @virt_devs: Pointer to return the array of virtual devices.
|
||||||
*
|
*
|
||||||
* This structure contains all information required for setting an OPP.
|
* This structure contains platform specific OPP configurations for the device.
|
||||||
*/
|
*/
|
||||||
struct dev_pm_set_opp_data {
|
struct dev_pm_opp_config {
|
||||||
struct dev_pm_opp_info old_opp;
|
/* NULL terminated */
|
||||||
struct dev_pm_opp_info new_opp;
|
const char * const *clk_names;
|
||||||
|
config_clks_t config_clks;
|
||||||
struct regulator **regulators;
|
const char *prop_name;
|
||||||
unsigned int regulator_count;
|
config_regulators_t config_regulators;
|
||||||
struct clk *clk;
|
const unsigned int *supported_hw;
|
||||||
struct device *dev;
|
unsigned int supported_hw_count;
|
||||||
|
const char * const *regulator_names;
|
||||||
|
const char * const *genpd_names;
|
||||||
|
struct device ***virt_devs;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_PM_OPP)
|
#if defined(CONFIG_PM_OPP)
|
||||||
@ -97,6 +99,8 @@ void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
|
|||||||
|
|
||||||
unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
|
unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
|
||||||
|
|
||||||
|
int dev_pm_opp_get_supplies(struct dev_pm_opp *opp, struct dev_pm_opp_supply *supplies);
|
||||||
|
|
||||||
unsigned long dev_pm_opp_get_power(struct dev_pm_opp *opp);
|
unsigned long dev_pm_opp_get_power(struct dev_pm_opp *opp);
|
||||||
|
|
||||||
unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
|
unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
|
||||||
@ -119,8 +123,6 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
|
|||||||
bool available);
|
bool available);
|
||||||
struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
|
struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
|
||||||
unsigned long *freq);
|
unsigned long *freq);
|
||||||
struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
|
|
||||||
unsigned long u_volt);
|
|
||||||
|
|
||||||
struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev,
|
struct dev_pm_opp *dev_pm_opp_find_level_exact(struct device *dev,
|
||||||
unsigned int level);
|
unsigned int level);
|
||||||
@ -154,23 +156,13 @@ int dev_pm_opp_disable(struct device *dev, unsigned long freq);
|
|||||||
int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb);
|
int dev_pm_opp_register_notifier(struct device *dev, struct notifier_block *nb);
|
||||||
int dev_pm_opp_unregister_notifier(struct device *dev, struct notifier_block *nb);
|
int dev_pm_opp_unregister_notifier(struct device *dev, struct notifier_block *nb);
|
||||||
|
|
||||||
struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions, unsigned int count);
|
int dev_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config);
|
||||||
void dev_pm_opp_put_supported_hw(struct opp_table *opp_table);
|
int devm_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config);
|
||||||
int devm_pm_opp_set_supported_hw(struct device *dev, const u32 *versions, unsigned int count);
|
void dev_pm_opp_clear_config(int token);
|
||||||
struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name);
|
int dev_pm_opp_config_clks_simple(struct device *dev,
|
||||||
void dev_pm_opp_put_prop_name(struct opp_table *opp_table);
|
struct opp_table *opp_table, struct dev_pm_opp *opp, void *data,
|
||||||
struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count);
|
bool scaling_down);
|
||||||
void dev_pm_opp_put_regulators(struct opp_table *opp_table);
|
|
||||||
int devm_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count);
|
|
||||||
struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name);
|
|
||||||
void dev_pm_opp_put_clkname(struct opp_table *opp_table);
|
|
||||||
int devm_pm_opp_set_clkname(struct device *dev, const char *name);
|
|
||||||
struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data));
|
|
||||||
void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table);
|
|
||||||
int devm_pm_opp_register_set_opp_helper(struct device *dev, int (*set_opp)(struct dev_pm_set_opp_data *data));
|
|
||||||
struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char * const *names, struct device ***virt_devs);
|
|
||||||
void dev_pm_opp_detach_genpd(struct opp_table *opp_table);
|
|
||||||
int devm_pm_opp_attach_genpd(struct device *dev, const char * const *names, struct device ***virt_devs);
|
|
||||||
struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table, struct opp_table *dst_table, struct dev_pm_opp *src_opp);
|
struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table, struct opp_table *dst_table, struct dev_pm_opp *src_opp);
|
||||||
int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate);
|
int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, struct opp_table *dst_table, unsigned int pstate);
|
||||||
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
|
int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
|
||||||
@ -198,6 +190,11 @@ static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int dev_pm_opp_get_supplies(struct dev_pm_opp *opp, struct dev_pm_opp_supply *supplies)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned long dev_pm_opp_get_power(struct dev_pm_opp *opp)
|
static inline unsigned long dev_pm_opp_get_power(struct dev_pm_opp *opp)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -274,12 +271,6 @@ static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
|
|||||||
return ERR_PTR(-EOPNOTSUPP);
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil_by_volt(struct device *dev,
|
|
||||||
unsigned long u_volt)
|
|
||||||
{
|
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
|
static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
|
||||||
unsigned long *freq)
|
unsigned long *freq)
|
||||||
{
|
{
|
||||||
@ -342,79 +333,21 @@ static inline int dev_pm_opp_unregister_notifier(struct device *dev, struct noti
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev,
|
static inline int dev_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config)
|
||||||
const u32 *versions,
|
|
||||||
unsigned int count)
|
|
||||||
{
|
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dev_pm_opp_put_supported_hw(struct opp_table *opp_table) {}
|
|
||||||
|
|
||||||
static inline int devm_pm_opp_set_supported_hw(struct device *dev,
|
|
||||||
const u32 *versions,
|
|
||||||
unsigned int count)
|
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct opp_table *dev_pm_opp_register_set_opp_helper(struct device *dev,
|
static inline int devm_pm_opp_set_config(struct device *dev, struct dev_pm_opp_config *config)
|
||||||
int (*set_opp)(struct dev_pm_set_opp_data *data))
|
|
||||||
{
|
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table) {}
|
|
||||||
|
|
||||||
static inline int devm_pm_opp_register_set_opp_helper(struct device *dev,
|
|
||||||
int (*set_opp)(struct dev_pm_set_opp_data *data))
|
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
|
static inline void dev_pm_opp_clear_config(int token) {}
|
||||||
{
|
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dev_pm_opp_put_prop_name(struct opp_table *opp_table) {}
|
static inline int dev_pm_opp_config_clks_simple(struct device *dev,
|
||||||
|
struct opp_table *opp_table, struct dev_pm_opp *opp, void *data,
|
||||||
static inline struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count)
|
bool scaling_down)
|
||||||
{
|
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dev_pm_opp_put_regulators(struct opp_table *opp_table) {}
|
|
||||||
|
|
||||||
static inline int devm_pm_opp_set_regulators(struct device *dev,
|
|
||||||
const char * const names[],
|
|
||||||
unsigned int count)
|
|
||||||
{
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct opp_table *dev_pm_opp_set_clkname(struct device *dev, const char *name)
|
|
||||||
{
|
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dev_pm_opp_put_clkname(struct opp_table *opp_table) {}
|
|
||||||
|
|
||||||
static inline int devm_pm_opp_set_clkname(struct device *dev, const char *name)
|
|
||||||
{
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct opp_table *dev_pm_opp_attach_genpd(struct device *dev, const char * const *names, struct device ***virt_devs)
|
|
||||||
{
|
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dev_pm_opp_detach_genpd(struct opp_table *opp_table) {}
|
|
||||||
|
|
||||||
static inline int devm_pm_opp_attach_genpd(struct device *dev,
|
|
||||||
const char * const *names,
|
|
||||||
struct device ***virt_devs)
|
|
||||||
{
|
{
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
@ -469,8 +402,6 @@ static inline int dev_pm_opp_sync_regulators(struct device *dev)
|
|||||||
int dev_pm_opp_of_add_table(struct device *dev);
|
int dev_pm_opp_of_add_table(struct device *dev);
|
||||||
int dev_pm_opp_of_add_table_indexed(struct device *dev, int index);
|
int dev_pm_opp_of_add_table_indexed(struct device *dev, int index);
|
||||||
int devm_pm_opp_of_add_table_indexed(struct device *dev, int index);
|
int devm_pm_opp_of_add_table_indexed(struct device *dev, int index);
|
||||||
int dev_pm_opp_of_add_table_noclk(struct device *dev, int index);
|
|
||||||
int devm_pm_opp_of_add_table_noclk(struct device *dev, int index);
|
|
||||||
void dev_pm_opp_of_remove_table(struct device *dev);
|
void dev_pm_opp_of_remove_table(struct device *dev);
|
||||||
int devm_pm_opp_of_add_table(struct device *dev);
|
int devm_pm_opp_of_add_table(struct device *dev);
|
||||||
int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask);
|
int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask);
|
||||||
@ -501,16 +432,6 @@ static inline int devm_pm_opp_of_add_table_indexed(struct device *dev, int index
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int dev_pm_opp_of_add_table_noclk(struct device *dev, int index)
|
|
||||||
{
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int devm_pm_opp_of_add_table_noclk(struct device *dev, int index)
|
|
||||||
{
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void dev_pm_opp_of_remove_table(struct device *dev)
|
static inline void dev_pm_opp_of_remove_table(struct device *dev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -565,4 +486,149 @@ static inline int dev_pm_opp_of_find_icc_paths(struct device *dev, struct opp_ta
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* OPP Configuration helpers */
|
||||||
|
|
||||||
|
/* Regulators helpers */
|
||||||
|
static inline int dev_pm_opp_set_regulators(struct device *dev,
|
||||||
|
const char * const names[])
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.regulator_names = names,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dev_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dev_pm_opp_put_regulators(int token)
|
||||||
|
{
|
||||||
|
dev_pm_opp_clear_config(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int devm_pm_opp_set_regulators(struct device *dev,
|
||||||
|
const char * const names[])
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.regulator_names = names,
|
||||||
|
};
|
||||||
|
|
||||||
|
return devm_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Supported-hw helpers */
|
||||||
|
static inline int dev_pm_opp_set_supported_hw(struct device *dev,
|
||||||
|
const u32 *versions,
|
||||||
|
unsigned int count)
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.supported_hw = versions,
|
||||||
|
.supported_hw_count = count,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dev_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dev_pm_opp_put_supported_hw(int token)
|
||||||
|
{
|
||||||
|
dev_pm_opp_clear_config(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int devm_pm_opp_set_supported_hw(struct device *dev,
|
||||||
|
const u32 *versions,
|
||||||
|
unsigned int count)
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.supported_hw = versions,
|
||||||
|
.supported_hw_count = count,
|
||||||
|
};
|
||||||
|
|
||||||
|
return devm_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clkname helpers */
|
||||||
|
static inline int dev_pm_opp_set_clkname(struct device *dev, const char *name)
|
||||||
|
{
|
||||||
|
const char *names[] = { name, NULL };
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.clk_names = names,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dev_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dev_pm_opp_put_clkname(int token)
|
||||||
|
{
|
||||||
|
dev_pm_opp_clear_config(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int devm_pm_opp_set_clkname(struct device *dev, const char *name)
|
||||||
|
{
|
||||||
|
const char *names[] = { name, NULL };
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.clk_names = names,
|
||||||
|
};
|
||||||
|
|
||||||
|
return devm_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* config-regulators helpers */
|
||||||
|
static inline int dev_pm_opp_set_config_regulators(struct device *dev,
|
||||||
|
config_regulators_t helper)
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.config_regulators = helper,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dev_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dev_pm_opp_put_config_regulators(int token)
|
||||||
|
{
|
||||||
|
dev_pm_opp_clear_config(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* genpd helpers */
|
||||||
|
static inline int dev_pm_opp_attach_genpd(struct device *dev,
|
||||||
|
const char * const *names,
|
||||||
|
struct device ***virt_devs)
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.genpd_names = names,
|
||||||
|
.virt_devs = virt_devs,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dev_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dev_pm_opp_detach_genpd(int token)
|
||||||
|
{
|
||||||
|
dev_pm_opp_clear_config(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int devm_pm_opp_attach_genpd(struct device *dev,
|
||||||
|
const char * const *names,
|
||||||
|
struct device ***virt_devs)
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.genpd_names = names,
|
||||||
|
.virt_devs = virt_devs,
|
||||||
|
};
|
||||||
|
|
||||||
|
return devm_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prop-name helpers */
|
||||||
|
static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
|
||||||
|
{
|
||||||
|
struct dev_pm_opp_config config = {
|
||||||
|
.prop_name = name,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dev_pm_opp_set_config(dev, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dev_pm_opp_put_prop_name(int token)
|
||||||
|
{
|
||||||
|
dev_pm_opp_clear_config(token);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __LINUX_OPP_H__ */
|
#endif /* __LINUX_OPP_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user